"use client";

import { toastApiError } from "@/lib/toast-api-error";
import * as React from "react";

import { zodResolver } from "@hookform/resolvers/zod";
import { Loader2, Save, Upload } from "lucide-react";
import { type Control, Controller, useForm } from "react-hook-form";
import { toast } from "sonner";
import { z } from "zod";

import { useDashboardFormSubmit } from "@/app/dashboard/_components/use-dashboard-form-submit";
import { customerCsrfHeader } from "@/lib/customer-csrf.client";
import { DatePicker } from "@/components/date-range-picker";
import { formDatePickerClass } from "@/components/form/common/form-layout";
import { FormField } from "@/components/form/form-field";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { cn } from "@/lib/utils";

import {
  CLIENT_RESIDENCIES,
  CLIENT_STATUSES,
  CLIENT_TYPES,
  DUE_DILIGENCE_LEVELS,
  PEP_OPTIONS,
  RELATIONSHIP_TYPES,
  RISK_PROFILE_LMH,
  RISK_PROFILES_5,
  type SelectOption,
} from "./account-info-constants";

type StaffOption = { id: number; name: string; email: string };

const NONE = "__none__";

const schema = z.object({
  ucap_unique_client_number: z.string().trim().min(1, "Client number is required"),
  client_type: z.string().min(1, "Client type is required"),
  client_residency: z.string().min(1, "Client residency is required"),
  client_status: z.string().min(1, "Client status is required"),
  pep: z.string(),
  relationship_type: z.string(),
  investment_risk_profile: z.string(),
  risk_tolerance: z.string(),
  risk_ability: z.string(),
  risk_profile: z.string(),
  level_of_due_diligence: z.string(),
  date_of_last_review: z.string(),
  date_of_next_review: z.string(),
  manager_id: z.string(),
  relationship_manager_name: z.string(),
  advisory_fee: z.string(),
  business_introducer_name: z.string(),
  business_introducer_fee: z.string(),
});

export type TenantCustomerAccountFormValues = z.infer<typeof schema>;

type TenantCustomerAccountFormProps = {
  tenant: string;
  customerId: number;
  initialValues: TenantCustomerAccountFormValues;
  staff: StaffOption[];
  documents: {
    passport_copy: string | null;
    second_id_copy: string | null;
    residence_proof_copy: string | null;
  };
};

/** Reusable react-hook-form <Select> wired to a string field. */
function SelectField({
  control,
  name,
  options,
  placeholder = "Please Select",
  clearable = true,
}: {
  control: Control<TenantCustomerAccountFormValues>;
  name: keyof TenantCustomerAccountFormValues;
  options: SelectOption[];
  placeholder?: string;
  clearable?: boolean;
}) {
  return (
    <Controller
      name={name}
      control={control}
      render={({ field }) => (
        <Select
          value={field.value === "" ? NONE : field.value}
          onValueChange={(value) => field.onChange(value === NONE ? "" : value)}
        >
          <SelectTrigger id={name}>
            <SelectValue placeholder={placeholder} />
          </SelectTrigger>
          <SelectContent>
            {clearable ? <SelectItem value={NONE}>{placeholder}</SelectItem> : null}
            {options.map((option) => (
              <SelectItem key={option.value} value={option.value}>
                {option.label}
              </SelectItem>
            ))}
          </SelectContent>
        </Select>
      )}
    />
  );
}

/** Shared calendar DatePicker (same as transaction forms), wired to a string ISO date field. */
function DatePickerField({
  control,
  name,
  id,
}: {
  control: Control<TenantCustomerAccountFormValues>;
  name: "date_of_last_review" | "date_of_next_review";
  id: string;
}) {
  return (
    <Controller
      name={name}
      control={control}
      render={({ field, fieldState }) => (
        <DatePicker
          id={id}
          value={field.value ?? ""}
          placeholder="Select date"
          align="start"
          aria-invalid={!!fieldState.error}
          className={cn(formDatePickerClass, "h-9")}
          onChange={field.onChange}
        />
      )}
    />
  );
}

const DOCUMENT_FIELDS = [
  { key: "passport_copy", label: "Passport Copy" },
  { key: "second_id_copy", label: "Second ID Copy" },
  { key: "residence_proof_copy", label: "Residence Proof Copy" },
] as const;

type DocumentKey = (typeof DOCUMENT_FIELDS)[number]["key"];

function basename(path: string) {
  return path.split("/").pop() || path;
}

function DocumentUploadField({
  tenant,
  uploadUrl,
  field,
  label,
  value,
  onUploaded,
}: {
  tenant: string;
  uploadUrl: string;
  field: DocumentKey;
  label: string;
  value: string | null;
  onUploaded: (field: DocumentKey, filepath: string) => void;
}) {
  const inputRef = React.useRef<HTMLInputElement>(null);
  const [uploading, setUploading] = React.useState(false);

  async function handleFile(file: File | undefined) {
    if (!file) {
      return;
    }
    setUploading(true);
    try {
      const body = new FormData();
      body.append("field", field);
      body.append("file", file);

      const response = await fetch(uploadUrl, {
        method: "POST",
        credentials: "same-origin",
        headers: customerCsrfHeader(tenant),
        body,
      });
      const payload = (await response.json().catch(() => null)) as
        | { status?: string; message?: string; data?: { filepath?: string } }
        | null;

      if (!response.ok || payload?.status !== "success" || !payload.data?.filepath) {
        throw new Error(payload?.message ?? "Could not upload the document.");
      }

      onUploaded(field, payload.data.filepath);
      toast.success(`${label} uploaded.`);
    } catch (error) {
      toastApiError(error, "Could not upload the document.");
    } finally {
      setUploading(false);
      if (inputRef.current) {
        inputRef.current.value = "";
      }
    }
  }

  return (
    <FormField
      label={label}
      htmlFor={field}
      description={value ? `Current: ${basename(value)}` : "No file uploaded yet."}
    >
      <input
        ref={inputRef}
        id={field}
        type="file"
        accept=".png,.jpg,.jpeg,.pdf"
        className="sr-only"
        onChange={(event) => void handleFile(event.target.files?.[0])}
      />
      <Button
        type="button"
        variant="outline"
        className="w-full justify-start"
        disabled={uploading}
        onClick={() => inputRef.current?.click()}
      >
        {uploading ? <Loader2 className="animate-spin" /> : <Upload />}
        {uploading ? "Uploading…" : value ? "Replace" : "Browse"}
      </Button>
    </FormField>
  );
}

export function TenantCustomerAccountForm({
  tenant,
  customerId,
  initialValues,
  staff,
  documents,
}: TenantCustomerAccountFormProps) {
  const listHref = `/customer/${tenant}/admin/customers`;
  const form = useForm<TenantCustomerAccountFormValues>({
    resolver: zodResolver(schema),
    defaultValues: initialValues,
  });
  const errors = form.formState.errors;

  const { isSaving, submit } = useDashboardFormSubmit<TenantCustomerAccountFormValues>({
    mode: "update",
    id: customerId,
    createUrl: "",
    updateUrl: `${listHref}/${customerId}/account`,
    listHref,
    timeoutMs: 120_000,
    saveFailMessage: "Account information could not be updated.",
    messages: {
      createFail: "Account information could not be saved.",
      updateFail: "Account information could not be updated.",
      createSuccess: "Account information updated.",
      updateSuccess: "Account information updated.",
    },
  });

  const managerOptions = React.useMemo<SelectOption[]>(
    () => staff.map((member) => ({ value: String(member.id), label: member.name || member.email })),
    [staff],
  );

  const uploadUrl = `${listHref}/${customerId}/documents`;
  const [documentPaths, setDocumentPaths] = React.useState(documents);

  function handleDocumentUploaded(field: DocumentKey, filepath: string) {
    setDocumentPaths((current) => ({ ...current, [field]: filepath }));
  }

  return (
    <form onSubmit={form.handleSubmit(submit)} className="flex min-h-full flex-col">
      <header className="mb-5 border-b pb-4">
        <h1 className="text-xl font-semibold tracking-tight">Update Account Information</h1>
        <p className="mt-1 text-sm text-muted-foreground">
          KYC, risk profile, and relationship details. Saved separately from the login profile.
        </p>
      </header>

      <div className="space-y-5 pb-24">
        <section className="grid gap-4 rounded-lg border bg-card p-4 md:grid-cols-2 xl:grid-cols-4">
          <FormField
            label="Unique Client Number"
            htmlFor="ucap_unique_client_number"
            required
            error={errors.ucap_unique_client_number}
          >
            <Input
              id="ucap_unique_client_number"
              placeholder="Unique Client Number"
              {...form.register("ucap_unique_client_number")}
            />
          </FormField>
          <FormField label="Client Type" htmlFor="client_type" required error={errors.client_type}>
            <SelectField
              control={form.control}
              name="client_type"
              options={CLIENT_TYPES}
              clearable={false}
            />
          </FormField>
          <FormField
            label="Client Residency"
            htmlFor="client_residency"
            required
            error={errors.client_residency}
          >
            <SelectField
              control={form.control}
              name="client_residency"
              options={CLIENT_RESIDENCIES}
              clearable={false}
            />
          </FormField>
          <FormField
            label="Client Status"
            htmlFor="client_status"
            required
            error={errors.client_status}
          >
            <SelectField
              control={form.control}
              name="client_status"
              options={CLIENT_STATUSES}
              clearable={false}
            />
          </FormField>
        </section>

        <section className="grid gap-4 rounded-lg border bg-card p-4 md:grid-cols-2 xl:grid-cols-4">
          <FormField label="PEP" htmlFor="pep">
            <SelectField control={form.control} name="pep" options={PEP_OPTIONS} />
          </FormField>
          <FormField label="Relationship Type" htmlFor="relationship_type">
            <SelectField
              control={form.control}
              name="relationship_type"
              options={RELATIONSHIP_TYPES}
            />
          </FormField>
          <FormField label="Investment Risk Profile" htmlFor="investment_risk_profile">
            <SelectField
              control={form.control}
              name="investment_risk_profile"
              options={RISK_PROFILES_5}
            />
          </FormField>
          <FormField label="Risk Tolerance" htmlFor="risk_tolerance">
            <SelectField control={form.control} name="risk_tolerance" options={RISK_PROFILES_5} />
          </FormField>

          <FormField label="Risk Ability" htmlFor="risk_ability">
            <SelectField control={form.control} name="risk_ability" options={RISK_PROFILES_5} />
          </FormField>
          <FormField label="Risk Profile" htmlFor="risk_profile">
            <SelectField control={form.control} name="risk_profile" options={RISK_PROFILE_LMH} />
          </FormField>
          <FormField label="Level Of Due Diligence" htmlFor="level_of_due_diligence">
            <SelectField
              control={form.control}
              name="level_of_due_diligence"
              options={DUE_DILIGENCE_LEVELS}
            />
          </FormField>
          <FormField label="Date Of Last Review" htmlFor="date_of_last_review">
            <DatePickerField
              control={form.control}
              name="date_of_last_review"
              id="date_of_last_review"
            />
          </FormField>

          <FormField label="Date Of Next Review" htmlFor="date_of_next_review">
            <DatePickerField
              control={form.control}
              name="date_of_next_review"
              id="date_of_next_review"
            />
          </FormField>
          <FormField label="Relationship Manager" htmlFor="manager_id">
            <SelectField control={form.control} name="manager_id" options={managerOptions} />
          </FormField>
          <FormField label="Relationship Manager Name" htmlFor="relationship_manager_name">
            <Input
              id="relationship_manager_name"
              placeholder="Relationship Manager Name"
              {...form.register("relationship_manager_name")}
            />
          </FormField>
          <FormField label="Advisory Fee" htmlFor="advisory_fee">
            <Input id="advisory_fee" placeholder="Advisory Fee" {...form.register("advisory_fee")} />
          </FormField>

          <FormField label="Business Introducer Name" htmlFor="business_introducer_name">
            <Input
              id="business_introducer_name"
              placeholder="Business Introducer Name"
              {...form.register("business_introducer_name")}
            />
          </FormField>
          <FormField label="Business Introducer Fee" htmlFor="business_introducer_fee">
            <Input
              id="business_introducer_fee"
              placeholder="Business Introducer Fee"
              {...form.register("business_introducer_fee")}
            />
          </FormField>
        </section>

        <section className="rounded-lg border bg-card p-4">
          <h2 className="text-lg font-semibold tracking-tight">Upload Documents</h2>
          <p className="mt-1 text-sm text-muted-foreground">
            PNG, JPG, or PDF up to 10 MB. Each file uploads and saves immediately —
            separately from the fields above.
          </p>
          <div className="mt-4 grid gap-4 md:grid-cols-2 xl:grid-cols-3">
            {DOCUMENT_FIELDS.map((doc) => (
              <DocumentUploadField
                key={doc.key}
                tenant={tenant}
                uploadUrl={uploadUrl}
                field={doc.key}
                label={doc.label}
                value={documentPaths[doc.key]}
                onUploaded={handleDocumentUploaded}
              />
            ))}
          </div>
        </section>
      </div>

      <footer className="sticky bottom-0 z-20 mt-auto flex items-center justify-end gap-3 border-t bg-background/95 px-4 py-3 shadow-[0_-4px_20px_-10px_rgba(0,0,0,0.3)] backdrop-blur">
        <Button type="submit" disabled={isSaving}>
          <Save />
          {isSaving ? "Saving…" : "Save changes"}
        </Button>
      </footer>
    </form>
  );
}
