import Link from "next/link";
import type {
  Paginated,
  SocialReportReason,
  SocialReportStatus,
  SocialReportSummary,
  SocialReportTargetType,
} from "@capila/contracts";
import { ProfileAvatar } from "@/components/profile-avatar";
import { formatTimestamp } from "@/lib/date-time";
import { getDictionary, type Locale } from "@/lib/i18n";
import { getLocale } from "@/lib/locale";
import { getAccessToken, getCurrentUser } from "@/lib/session";
import { updateReportStatus } from "./actions";

type SearchParams = {
  targetType?: string;
  status?: string;
  reason?: string;
  page?: string;
  success?: string;
  error?: string;
};

const targetTypes: SocialReportTargetType[] = ["USER", "POST", "COMMENT"];
const statuses: SocialReportStatus[] = [
  "PENDING",
  "REVIEWING",
  "RESOLVED",
  "REJECTED",
];
const reasons: SocialReportReason[] = [
  "SPAM",
  "NUDITY",
  "VIOLENCE",
  "HATE",
  "HARASSMENT",
  "FALSE_INFORMATION",
  "SCAM",
  "INTELLECTUAL_PROPERTY",
  "OTHER",
];

export default async function ReportsPage({
  searchParams,
}: {
  searchParams: Promise<SearchParams>;
}) {
  const params = await searchParams;
  const locale = await getLocale();
  const copy = getDictionary(locale).reports;
  const currentUser = await getCurrentUser(locale);
  if (!currentUser?.permissions.includes("content:moderate")) {
    return (
      <section className="surface placeholder">
        <h1>{copy.denied}</h1>
      </section>
    );
  }
  const page = Math.max(1, Number(params.page) || 1);
  const token = await getAccessToken();
  const result = token
    ? await loadReports(token, locale, page, params)
    : emptyResult(page);

  return (
    <>
      <div className="page-heading">
        <div>
          <p className="eyebrow">{copy.eyebrow}</p>
          <h1>{copy.title}</h1>
          <p className="page-description">{copy.description}</p>
        </div>
        <span className="badge">{result.meta.total}</span>
      </div>

      <form className="surface report-filters" method="get">
        <FilterSelect
          name="targetType"
          label={copy.type}
          value={params.targetType}
          all={copy.all}
          options={targetTypes.map((value) => ({
            value,
            label: targetLabel(value, copy),
          }))}
        />
        <FilterSelect
          name="status"
          label={copy.status}
          value={params.status}
          all={copy.all}
          options={statuses.map((value) => ({
            value,
            label: statusLabel(value, copy),
          }))}
        />
        <FilterSelect
          name="reason"
          label={copy.reason}
          value={params.reason}
          all={copy.all}
          options={reasons.map((value) => ({
            value,
            label: copy.reasons[value],
          }))}
        />
        <button className="primary-button" type="submit">
          {copy.apply}
        </button>
      </form>

      {result.data.length === 0 ? (
        <section className="surface placeholder">
          <p>{copy.empty}</p>
        </section>
      ) : (
        <section className="report-grid">
          {result.data.map((report) => (
            <article className="surface report-card" key={report.id}>
              <header className="report-card-header">
                <span
                  className={`report-status report-status-${report.status.toLowerCase()}`}
                >
                  {statusLabel(report.status, copy)}
                </span>
                <span className="badge">
                  {targetLabel(report.targetType, copy)}
                </span>
                <time>{formatTimestamp(report.createdAt, locale)}</time>
              </header>

              <div className="report-parties">
                <ReportParty label={copy.reporter} user={report.reporter} />
                <ReportParty
                  label={copy.target}
                  user={report.target.owner}
                  missingLabel={copy.targetMissing}
                />
              </div>

              <dl className="report-details">
                <div>
                  <dt>{copy.reason}</dt>
                  <dd>{copy.reasons[report.reason]}</dd>
                </div>
                <div>
                  <dt>{copy.details}</dt>
                  <dd>{report.details || "—"}</dd>
                </div>
                {report.target.preview ? (
                  <div>
                    <dt>{targetLabel(report.targetType, copy)}</dt>
                    <dd>{report.target.preview}</dd>
                  </div>
                ) : null}
              </dl>

              <form className="report-status-form" action={updateReportStatus}>
                <input type="hidden" name="reportId" value={report.id} />
                <label>
                  <span>{copy.status}</span>
                  <select name="status" defaultValue={report.status}>
                    {statuses.map((status) => (
                      <option key={status} value={status}>
                        {statusLabel(status, copy)}
                      </option>
                    ))}
                  </select>
                </label>
                <button className="secondary-button" type="submit">
                  {copy.update}
                </button>
              </form>
            </article>
          ))}
        </section>
      )}

      {result.meta.pageCount > 1 ? (
        <nav className="pagination" aria-label={copy.title}>
          <PaginationLink
            label={copy.previous}
            page={page - 1}
            disabled={page <= 1}
            params={params}
          />
          <span>
            {result.meta.page} / {result.meta.pageCount}
          </span>
          <PaginationLink
            label={copy.next}
            page={page + 1}
            disabled={page >= result.meta.pageCount}
            params={params}
          />
        </nav>
      ) : null}
    </>
  );
}

function FilterSelect({
  name,
  label,
  value,
  all,
  options,
}: {
  name: string;
  label: string;
  value: string | undefined;
  all: string;
  options: { value: string; label: string }[];
}) {
  return (
    <label>
      <span>{label}</span>
      <select name={name} defaultValue={value ?? ""}>
        <option value="">{all}</option>
        {options.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>
    </label>
  );
}

function ReportParty({
  label,
  user,
  missingLabel,
}: {
  label: string;
  user: SocialReportSummary["reporter"] | null;
  missingLabel?: string;
}) {
  return (
    <div className="report-party">
      <span>{label}</span>
      {user ? (
        <Link href={`/app-users/${user.id}`}>
          <ProfileAvatar
            className="report-party-avatar profile-image-avatar"
            image={user.profileImage}
            displayName={user.displayName}
          />
          <strong>{user.displayName}</strong>
          <small>{user.username ? `@${user.username}` : "—"}</small>
        </Link>
      ) : (
        <p>{missingLabel ?? "—"}</p>
      )}
    </div>
  );
}

function PaginationLink({
  label,
  page,
  disabled,
  params,
}: {
  label: string;
  page: number;
  disabled: boolean;
  params: SearchParams;
}) {
  if (disabled) return <span className="pagination-disabled">{label}</span>;
  const query = new URLSearchParams();
  query.set("page", String(page));
  for (const key of ["targetType", "status", "reason"] as const) {
    if (params[key]) query.set(key, params[key]!);
  }
  return <Link href={`/reports?${query.toString()}`}>{label}</Link>;
}

const loadReports = async (
  token: string,
  locale: Locale,
  page: number,
  filters: SearchParams,
): Promise<Paginated<SocialReportSummary>> => {
  const params = new URLSearchParams({ page: String(page), pageSize: "20" });
  for (const key of ["targetType", "status", "reason"] as const) {
    if (filters[key]) params.set(key, filters[key]!);
  }
  try {
    const response = await fetch(
      `${process.env.API_URL ?? "http://localhost:3001/api/v1"}/panel/social/reports?${params}`,
      {
        headers: {
          authorization: `Bearer ${token}`,
          "accept-language": locale,
        },
        cache: "no-store",
      },
    );
    return response.ok
      ? ((await response.json()) as Paginated<SocialReportSummary>)
      : emptyResult(page);
  } catch {
    return emptyResult(page);
  }
};

const emptyResult = (page: number): Paginated<SocialReportSummary> => ({
  data: [],
  meta: { page, pageSize: 20, total: 0, pageCount: 0 },
});

const targetLabel = (
  value: SocialReportTargetType,
  copy: ReturnType<typeof getDictionary>["reports"],
) =>
  value === "USER" ? copy.user : value === "POST" ? copy.post : copy.comment;

const statusLabel = (
  value: SocialReportStatus,
  copy: ReturnType<typeof getDictionary>["reports"],
) =>
  value === "PENDING"
    ? copy.pending
    : value === "REVIEWING"
      ? copy.reviewing
      : value === "RESOLVED"
        ? copy.resolved
        : copy.rejected;
