import type { ProjectDetail } from "@/lib/metrics";
import { createDocumentAction, deleteProjectScopedRecordAction, updateDocumentAction } from "@/app/actions";
import { AppShell } from "@/components/AppShell";
import { DeleteButton } from "@/components/DeleteButton";
import { DocumentUploader } from "@/components/DocumentUploader";
import { DocumentViewer } from "@/components/DocumentViewer";
import { EmptyState } from "@/components/EmptyState";
import { PageHeader } from "@/components/PageHeader";
import { StatusMessage } from "@/components/StatusMessage";
import { SummaryCard } from "@/components/SummaryCard";
import { documentStatusLabels, reminderStatusLabels } from "@/lib/documents";
import { currency, dateInput, shortDate } from "@/lib/format";
import { buildProjectMetrics } from "@/lib/metrics";
import { getSelectedProject } from "@/lib/projects";

type DocumentRecord = ProjectDetail["documents"][number];

type DocumentFilters = {
  projectId?: string;
  category: string;
  status: string;
  tenant: string;
  unit: string;
  partner: string;
  from: string;
  to: string;
  search: string;
  expiringSoon: boolean;
};

function oneParam(params: Record<string, string | string[] | undefined>, key: string) {
  const value = params[key];
  return Array.isArray(value) ? value[0] ?? "" : value ?? "";
}

function parseDocumentFilters(params: Record<string, string | string[] | undefined>): DocumentFilters {
  return {
    projectId: oneParam(params, "projectId") || undefined,
    category: oneParam(params, "category"),
    status: oneParam(params, "status"),
    tenant: oneParam(params, "tenant"),
    unit: oneParam(params, "unit"),
    partner: oneParam(params, "partner"),
    from: oneParam(params, "from"),
    to: oneParam(params, "to"),
    search: oneParam(params, "search"),
    expiringSoon: oneParam(params, "expiringSoon") === "1"
  };
}

function dateFilter(value: string, endOfDay = false) {
  if (!value) return null;
  const date = new Date(`${value}T${endOfDay ? "23:59:59.999" : "00:00:00.000"}`);
  return Number.isNaN(date.getTime()) ? null : date;
}

function documentDate(document: DocumentRecord) {
  return document.documentDate ?? document.createdAt;
}

function relatedText(document: DocumentRecord) {
  const values = [
    document.relatedTenant ? `Tenant: ${document.relatedTenant.name}` : "",
    document.relatedUnit ? `Unit: ${document.relatedUnit.name}` : "",
    document.relatedPartner ? `Partner: ${document.relatedPartner.partner.name}` : "",
    document.relatedExpense ? `Expense: ${document.relatedExpense.vendor ?? document.relatedExpense.description ?? document.relatedExpense.category?.name ?? "Record"}` : "",
    document.relatedRentPayment ? `Rent: ${document.relatedRentPayment.tenant.name} ${document.relatedRentPayment.month.toISOString().slice(0, 7)}` : ""
  ].filter(Boolean);

  return values.length > 0 ? values.join(" | ") : "-";
}

function documentFiles(document: DocumentRecord) {
  if (document.files.length > 0) {
    return document.files.map((file) => ({
      id: file.id,
      fileName: file.fileName,
      fileUrl: file.fileUrl,
      fileMimeType: file.mimeType
    }));
  }
  return [{
    id: document.id,
    fileName: document.fileName,
    fileUrl: document.fileUrl,
    fileMimeType: document.fileMimeType
  }];
}

function statusClass(status: string) {
  if (status === "EXPIRED") return "bg-red-50 text-red-700";
  if (status === "NEEDS_REVIEW" || status === "PENDING") return "bg-amber-50 text-amber-700";
  if (status === "ARCHIVED") return "bg-slate-100 text-slate-600";
  return "bg-emerald-50 text-emerald-700";
}

function filterDocuments(documents: DocumentRecord[], filters: DocumentFilters) {
  const from = dateFilter(filters.from);
  const to = dateFilter(filters.to, true);
  const search = filters.search.trim().toLowerCase();
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  const soon = new Date(today);
  soon.setDate(soon.getDate() + 30);

  return documents.filter((document) => {
    const date = documentDate(document);
    if (filters.category && document.categoryId !== filters.category) return false;
    if (filters.status && document.status !== filters.status) return false;
    if (filters.tenant && document.relatedTenantId !== filters.tenant) return false;
    if (filters.unit && document.relatedUnitId !== filters.unit) return false;
    if (filters.partner && document.relatedPartnerId !== filters.partner) return false;
    if (from && date < from) return false;
    if (to && date > to) return false;
    if (filters.expiringSoon && (!document.expirationDate || document.expirationDate < today || document.expirationDate > soon)) return false;
    if (search) {
      const haystack = [
        document.title,
        document.documentType,
        document.fileName,
        ...document.files.map((file) => file.fileName),
        document.notes,
        document.tags,
        document.category?.name,
        document.relatedTenant?.name,
        document.relatedUnit?.name,
        document.relatedPartner?.partner.name
      ]
        .filter(Boolean)
        .join(" ")
        .toLowerCase();
      if (!haystack.includes(search)) return false;
    }
    return true;
  });
}

function DocumentFields({
  project,
  document,
  multiple = false
}: {
  project: ProjectDetail;
  document?: DocumentRecord;
  multiple?: boolean;
}) {
  const categoryOptions = project.documentCategories.filter(
    (category) => !category.archived || category.id === document?.categoryId
  );
  const primaryFile = document ? documentFiles(document)[0] : null;

  return (
    <>
      <div className="grid gap-4 md:grid-cols-2">
        <label className="grid gap-2">
          <span className="label">Document title</span>
          <input className="field" name="title" defaultValue={document?.title ?? ""} required />
        </label>
        <label className="grid gap-2">
          <span className="label">Document type</span>
          <input className="field" name="documentType" defaultValue={document?.documentType ?? ""} placeholder="Lease, insurance, closing statement" />
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-2">
        <label className="grid gap-2">
          <span className="label">Category</span>
          <select className="field" name="categoryId" defaultValue={document?.categoryId ?? ""}>
            <option value="">Uncategorized</option>
            {categoryOptions.map((category) => (
              <option key={category.id} value={category.id}>
                {category.name}{category.archived ? " (archived)" : ""}
              </option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Status</span>
          <select className="field" name="status" defaultValue={document?.status ?? "ACTIVE"}>
            {Object.entries(documentStatusLabels).map(([value, label]) => (
              <option key={value} value={value}>{label}</option>
            ))}
          </select>
        </label>
      </div>

      <DocumentUploader
        multiple={multiple}
        existingUrl={primaryFile?.fileUrl}
        existingFileName={primaryFile?.fileName}
        existingMimeType={primaryFile?.fileMimeType}
      />

      <div className="grid gap-4 md:grid-cols-3">
        <label className="grid gap-2">
          <span className="label">Document date</span>
          <input className="field" name="documentDate" type="date" defaultValue={dateInput(document?.documentDate)} />
        </label>
        <label className="grid gap-2">
          <span className="label">Expiration date</span>
          <input className="field" name="expirationDate" type="date" defaultValue={dateInput(document?.expirationDate)} />
        </label>
        <label className="grid gap-2">
          <span className="label">Renewal date</span>
          <input className="field" name="renewalDate" type="date" defaultValue={dateInput(document?.renewalDate)} />
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-3">
        <label className="grid gap-2">
          <span className="label">Tenant</span>
          <select className="field" name="relatedTenantId" defaultValue={document?.relatedTenantId ?? ""}>
            <option value="">None</option>
            {project.tenants.map((tenant) => (
              <option key={tenant.id} value={tenant.id}>{tenant.name}</option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Unit</span>
          <select className="field" name="relatedUnitId" defaultValue={document?.relatedUnitId ?? ""}>
            <option value="">None</option>
            {project.units.map((unit) => (
              <option key={unit.id} value={unit.id}>{unit.name}</option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Partner</span>
          <select className="field" name="relatedPartnerId" defaultValue={document?.relatedPartnerId ?? ""}>
            <option value="">None</option>
            {project.partners.map((partner) => (
              <option key={partner.id} value={partner.id}>{partner.partner.name}</option>
            ))}
          </select>
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-2">
        <label className="grid gap-2">
          <span className="label">Expense record</span>
          <select className="field" name="relatedExpenseId" defaultValue={document?.relatedExpenseId ?? ""}>
            <option value="">None</option>
            {project.expenses.map((expense) => (
              <option key={expense.id} value={expense.id}>
                {shortDate(expense.date)} - {expense.vendor ?? expense.description ?? expense.category?.name ?? "Expense"} - {currency(Number(expense.finalCost))}
              </option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Rent payment</span>
          <select className="field" name="relatedRentPaymentId" defaultValue={document?.relatedRentPaymentId ?? ""}>
            <option value="">None</option>
            {project.rentPayments.map((payment) => (
              <option key={payment.id} value={payment.id}>
                {payment.tenant.name} - {payment.month.toISOString().slice(0, 7)} - {currency(Number(payment.rentPaid))}
              </option>
            ))}
          </select>
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-2">
        <label className="grid gap-2">
          <span className="label">Tags</span>
          <input className="field" name="tags" defaultValue={document?.tags ?? ""} placeholder="lease, 2026, insurance" />
        </label>
        <label className="grid gap-2">
          <span className="label">Reminder date</span>
          <input className="field" name="reminderDate" type="date" defaultValue={dateInput(document?.reminderDate)} />
        </label>
      </div>

      <div className="grid gap-4 md:grid-cols-2">
        <label className="grid gap-2">
          <span className="label">Reminder status</span>
          <select className="field" name="reminderStatus" defaultValue={document?.reminderStatus ?? "OPEN"}>
            {Object.entries(reminderStatusLabels).map(([value, label]) => (
              <option key={value} value={value}>{label}</option>
            ))}
          </select>
        </label>
        <label className="grid gap-2">
          <span className="label">Reminder note</span>
          <input className="field" name="reminderNote" defaultValue={document?.reminderNote ?? ""} />
        </label>
      </div>

      <label className="grid gap-2">
        <span className="label">Notes</span>
        <textarea className="field min-h-20" name="notes" defaultValue={document?.notes ?? ""} />
      </label>
    </>
  );
}

export default async function DocumentsPage({
  searchParams
}: {
  searchParams?: Promise<Record<string, string | string[] | undefined>>;
}) {
  const params = (await searchParams) ?? {};
  const filters = parseDocumentFilters(params);
  const { user, projects, project, permissions, projectRole } = await getSelectedProject(filters.projectId, "documents.view");
  const canEdit = Boolean(permissions?.["documents.upload"] || permissions?.["documents.edit"] || permissions?.["documents.archive"] || permissions?.["documents.delete"]);

  if (!project) {
    return (
      <AppShell projects={projects} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
        <EmptyState title="Create a project before managing documents." href="/projects" actionLabel="Create project" />
      </AppShell>
    );
  }

  const metrics = buildProjectMetrics(project);
  const filteredDocuments = filterDocuments(project.documents, filters);
  const activeCategories = project.documentCategories.filter((category) => !category.archived);

  return (
    <AppShell projects={projects} selectedProjectId={project.id} username={user.name ?? user.username ?? user.email} role={projectRole ?? user.role} permissions={permissions}>
      <PageHeader
        title="Documents"
        description="File cabinet for property, purchase, tenant, insurance, legal, and partner records."
      />
      <StatusMessage updated={params.updated} deleted={params.deleted} error={params.error} />

      <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <SummaryCard label="Total documents" value={String(metrics.totalDocuments)} />
        <SummaryCard label="Needs review" value={String(metrics.documentsNeedingReview)} />
        <SummaryCard label="Expiring soon" value={String(metrics.expiringSoonDocuments)} />
        <SummaryCard label="Expired" value={String(metrics.expiredDocuments)} />
      </section>

      <section className="mt-6 grid gap-6 xl:grid-cols-[0.9fr_1.1fr]">
        {canEdit ? (
          <form action={createDocumentAction} className="panel grid gap-4 p-4">
            <h3 className="font-semibold text-ink">Add Documents</h3>
            <input type="hidden" name="projectId" value={project.id} />
            <DocumentFields project={project} multiple />
            <button className="btn-primary">Save document</button>
          </form>
        ) : null}

        <div className="grid gap-4">
          <form className="panel grid gap-3 p-4 md:grid-cols-2" action="/documents">
            <input type="hidden" name="projectId" value={project.id} />
            <input className="field" name="search" placeholder="Title, notes, tags" defaultValue={filters.search} />
            <select className="field" name="category" defaultValue={filters.category}>
              <option value="">All document categories</option>
              {project.documentCategories.map((category) => (
                <option key={category.id} value={category.id}>{category.name}</option>
              ))}
            </select>
            <select className="field" name="status" defaultValue={filters.status}>
              <option value="">All statuses</option>
              {Object.entries(documentStatusLabels).map(([value, label]) => (
                <option key={value} value={value}>{label}</option>
              ))}
            </select>
            <select className="field" name="tenant" defaultValue={filters.tenant}>
              <option value="">All tenants</option>
              {project.tenants.map((tenant) => (
                <option key={tenant.id} value={tenant.id}>{tenant.name}</option>
              ))}
            </select>
            <select className="field" name="unit" defaultValue={filters.unit}>
              <option value="">All units</option>
              {project.units.map((unit) => (
                <option key={unit.id} value={unit.id}>{unit.name}</option>
              ))}
            </select>
            <select className="field" name="partner" defaultValue={filters.partner}>
              <option value="">All partners</option>
              {project.partners.map((partner) => (
                <option key={partner.id} value={partner.id}>{partner.partner.name}</option>
              ))}
            </select>
            <input className="field" name="from" type="date" defaultValue={filters.from} title="From document date" />
            <input className="field" name="to" type="date" defaultValue={filters.to} title="To document date" />
            <label className="flex items-center gap-2 rounded-md border border-line bg-white px-3 py-2 text-sm font-medium text-slate-700">
              <input className="h-4 w-4 rounded border-line" name="expiringSoon" type="checkbox" value="1" defaultChecked={filters.expiringSoon} />
              Expiring soon
            </label>
            <div className="flex flex-wrap gap-2 md:col-span-2">
              <button className="btn-secondary">Apply filters</button>
              <a className="btn-secondary" href={`/documents?projectId=${project.id}`}>Reset</a>
              <a className="btn-secondary" href={`/settings/categories?projectId=${project.id}`}>Manage categories</a>
            </div>
          </form>

          <section className="grid gap-4 md:grid-cols-3">
            <SummaryCard label="Tenant / lease" value={String(metrics.tenantLeaseDocuments)} />
            <SummaryCard label="Insurance" value={String(metrics.insuranceDocuments)} />
            <SummaryCard label="Active categories" value={String(activeCategories.length)} />
          </section>
        </div>
      </section>

      <section className="panel mt-6 overflow-hidden">
        <div className="flex flex-col gap-2 border-b border-line px-4 py-3 md:flex-row md:items-center md:justify-between">
          <h3 className="font-semibold text-ink">Document List</h3>
          <p className="text-sm text-slate-500">{filteredDocuments.length} shown</p>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full min-w-[1320px]">
            <thead className="table-head">
              <tr>
                <th className="px-3 py-2">Title</th>
                <th className="px-3 py-2">Category</th>
                <th className="px-3 py-2">Status</th>
                <th className="px-3 py-2">Document date</th>
                <th className="px-3 py-2">Expiration</th>
                <th className="px-3 py-2">Related to</th>
                <th className="px-3 py-2">Tags</th>
                <th className="px-3 py-2">File</th>
                {canEdit ? <th className="px-3 py-2">Actions</th> : null}
              </tr>
            </thead>
            <tbody>
              {filteredDocuments.map((document) => {
                const files = documentFiles(document);
                return (
                <tr key={document.id}>
                  <td className="table-cell">
                    <div className="font-medium text-ink">{document.title}</div>
                    <div className="text-xs text-slate-500">
                      {document.documentType ?? "Document group"} - {files.length} {files.length === 1 ? "file" : "files"}
                    </div>
                  </td>
                  <td className="table-cell">{document.category?.name ?? "-"}</td>
                  <td className="table-cell">
                    <span className={`inline-flex rounded-md px-2 py-1 text-xs font-semibold ${statusClass(document.status)}`}>
                      {documentStatusLabels[document.status]}
                    </span>
                  </td>
                  <td className="table-cell">{shortDate(document.documentDate)}</td>
                  <td className="table-cell">{shortDate(document.expirationDate)}</td>
                  <td className="table-cell">{relatedText(document)}</td>
                  <td className="table-cell">{document.tags ?? "-"}</td>
                  <td className="table-cell">
                    {files.length === 1 ? (
                      <DocumentViewer
                        url={files[0].fileUrl}
                        fileName={files[0].fileName}
                        mimeType={files[0].fileMimeType}
                        buttonLabel="View"
                        emptyLabel="No document"
                        compact
                      />
                    ) : (
                      <details className="detail-toggle">
                        <summary>View Files ({files.length})</summary>
                        <div className="mt-3 grid min-w-[320px] gap-2">
                          {files.map((file, index) => (
                            <div key={file.id} className="flex flex-wrap items-center justify-between gap-2 rounded-md border border-line bg-white p-2">
                              <span className="max-w-48 truncate text-sm font-medium text-ink">{file.fileName ?? `File ${index + 1}`}</span>
                              <DocumentViewer
                                url={file.fileUrl}
                                fileName={file.fileName}
                                mimeType={file.fileMimeType}
                                buttonLabel="View"
                                emptyLabel="No document"
                                compact
                              />
                            </div>
                          ))}
                        </div>
                      </details>
                    )}
                  </td>
                  {canEdit ? (
                    <td className="table-cell align-top">
                      <div className="flex flex-wrap gap-2">
                        <details className="action-modal">
                          <summary>Edit</summary>
                          <form action={updateDocumentAction} className="mt-3 grid min-w-[420px] gap-3">
                            <input type="hidden" name="projectId" value={project.id} />
                            <input type="hidden" name="documentId" value={document.id} />
                            <DocumentFields project={project} document={document} />
                            <button className="btn-primary">Update document</button>
                          </form>
                        </details>
                        <form action={deleteProjectScopedRecordAction}>
                          <input type="hidden" name="projectId" value={project.id} />
                          <input type="hidden" name="model" value="document" />
                          <input type="hidden" name="id" value={document.id} />
                          <input type="hidden" name="returnTo" value="/documents" />
                          <DeleteButton label="Delete document" message={`Delete ${document.title}? This removes the saved file from the cabinet.`} />
                        </form>
                      </div>
                    </td>
                  ) : null}
                </tr>
                );
              })}
            </tbody>
          </table>
          {filteredDocuments.length === 0 ? (
            <div className="p-6 text-sm text-slate-600">No documents match this project and filter.</div>
          ) : null}
        </div>
      </section>
    </AppShell>
  );
}
