"use client";

import { FormEvent, useEffect, useMemo, useState } from "react";

import { useLocale } from "@/components/providers/locale-provider";
import { PaginationFooter } from "@/components/shared/pagination-footer";
import { useCurrentUser } from "@/hooks/use-current-user";
import { usePagination } from "@/hooks/use-pagination";
import { formatCurrencyAmount } from "@/lib/formatters";
import type { ApiErrorResponse, DetailResponse } from "@/types/api";
import type {
  BankRecord,
  SalesDetailRecord,
  SalesRecord
} from "@/types/master-data";

type BankAccountForm = {
  bank_id: string;
  account_number: string;
};

type SalesForm = {
  code: string;
  name: string;
  identity_type: "KTP" | "SIM" | "PASSPORT";
  identity_number: string;
  mobile_phone: string;
  email: string;
  address: string;
  notes: string;
  join_date: string;
  bank_accounts: BankAccountForm[];
};

const emptyBankAccount = (): BankAccountForm => ({
  bank_id: "",
  account_number: ""
});

const emptyForm = (): SalesForm => ({
  code: "",
  name: "",
  identity_type: "KTP",
  identity_number: "",
  mobile_phone: "",
  email: "",
  address: "",
  notes: "",
  join_date: new Date().toISOString().slice(0, 10),
  bank_accounts: [emptyBankAccount()]
});

export function SalesClient() {
  const { dict, locale } = useLocale();
  const { canEditCode } = useCurrentUser();
  const [salesList, setSalesList] = useState<SalesRecord[]>([]);
  const [search, setSearch] = useState("");
  const [banks, setBanks] = useState<BankRecord[]>([]);
  const [form, setForm] = useState<SalesForm>(emptyForm);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [selectedSalesId, setSelectedSalesId] = useState<string | null>(null);
  const [selectedSalesDetail, setSelectedSalesDetail] = useState<SalesDetailRecord | null>(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const filteredSales = useMemo(() => {
    const keyword = search.trim().toLowerCase();
    if (!keyword) return salesList;
    return salesList.filter((sales) =>
      [
        sales.code,
        sales.name,
        sales.identity_type,
        sales.identity_number,
        sales.mobile_phone ?? "",
        sales.email ?? "",
        sales.address ?? ""
      ].some((value) => value.toLowerCase().includes(keyword))
    );
  }, [salesList, search]);
  const pagination = usePagination(filteredSales, 20);

  async function loadData() {
    setLoading(true);
    setError(null);

    try {
      const [salesResponse, banksResponse] = await Promise.all([
        fetch("/api/v1/sales", { cache: "no-store" }),
        fetch("/api/v1/banks", { cache: "no-store" })
      ]);

      const salesPayload = (await salesResponse.json()) as { data: SalesRecord[] };
      const banksPayload = (await banksResponse.json()) as { data: BankRecord[] };

      if (!salesResponse.ok || !banksResponse.ok) {
        throw new Error(dict.master.loadError);
      }

      setSalesList(salesPayload.data);
      setBanks(banksPayload.data.filter((bank) => bank.status === "ACTIVE"));
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.master.loadError);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void loadData();
  }, []);

  async function openDetail(id: string) {
    setSelectedSalesId(id);
    setDetailLoading(true);

    try {
      const response = await fetch(`/api/v1/sales/${id}/detail`, { cache: "no-store" });
      const payload = (await response.json()) as DetailResponse<SalesDetailRecord> | ApiErrorResponse;

      if (!response.ok || !("data" in payload)) {
        throw new Error("message" in payload ? payload.message : dict.common.requestFailed);
      }

      setSelectedSalesDetail(payload.data);
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.common.requestFailed);
    } finally {
      setDetailLoading(false);
    }
  }

  function resetForm() {
    setEditingId(null);
    setForm(emptyForm());
    setError(null);
  }

  function startEdit(sales: SalesRecord) {
    setEditingId(sales.id);
    setForm({
      code: sales.code,
      name: sales.name,
      identity_type: sales.identity_type,
      identity_number: sales.identity_number,
      mobile_phone: sales.mobile_phone ?? "",
      email: sales.email ?? "",
      address: sales.address ?? "",
      notes: sales.notes ?? "",
      join_date: sales.join_date,
      bank_accounts:
        sales.bank_accounts.length > 0
          ? sales.bank_accounts.map((account) => ({
              bank_id: account.bank_id,
              account_number: account.account_number
            }))
          : [emptyBankAccount()]
    });
    setError(null);
  }

  function updateBankAccount(index: number, patch: Partial<BankAccountForm>) {
    setForm((current) => ({
      ...current,
      bank_accounts: current.bank_accounts.map((account, itemIndex) =>
        itemIndex === index ? { ...account, ...patch } : account
      )
    }));
  }

  function addBankAccount() {
    setForm((current) => ({
      ...current,
      bank_accounts: [...current.bank_accounts, emptyBankAccount()]
    }));
  }

  function removeBankAccount(index: number) {
    setForm((current) => ({
      ...current,
      bank_accounts:
        current.bank_accounts.length === 1
          ? current.bank_accounts
          : current.bank_accounts.filter((_, itemIndex) => itemIndex !== index)
    }));
  }

  async function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    setSubmitting(true);
    setError(null);

    try {
      const response = await fetch(editingId ? `/api/v1/sales/${editingId}` : "/api/v1/sales", {
        method: editingId ? "PUT" : "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(form)
      });

      const payload = (await response.json()) as DetailResponse<SalesRecord> | ApiErrorResponse;

      if (!response.ok) {
        if ("errors" in payload && payload.errors) {
          const firstError = Object.values(payload.errors)[0]?.[0];
          throw new Error(firstError ?? payload.message ?? dict.common.requestFailed);
        }

        throw new Error("message" in payload ? payload.message : dict.common.requestFailed);
      }

      resetForm();
      await loadData();
      if (selectedSalesId) {
        await openDetail(selectedSalesId);
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.master.saveError);
    } finally {
      setSubmitting(false);
    }
  }

  async function handleDelete(id: string) {
    if (!window.confirm(`${dict.common.delete} sales ini?`)) return;

    try {
      const response = await fetch(`/api/v1/sales/${id}`, { method: "DELETE" });
      if (!response.ok) {
        const payload = (await response.json()) as ApiErrorResponse;
        throw new Error(payload.message);
      }

      if (editingId === id) resetForm();
      if (selectedSalesId === id) {
        setSelectedSalesId(null);
        setSelectedSalesDetail(null);
      }
      await loadData();
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.master.deleteError);
    }
  }

  return (
    <section className="grid gap-6 xl:grid-cols-[1.02fr_0.98fr]">
      <div className="ops-card p-6">
        <div className="flex items-start justify-between gap-4">
          <div>
            <p className="ops-overline">{dict.master.overline}</p>
            <h2 className="mt-2 text-[28px] font-semibold tracking-tight text-ink">
              {editingId ? (locale === "id" ? `${dict.common.edit} Sales` : `${dict.common.edit} Sales`) : (locale === "id" ? `${dict.master.add} Sales` : `${dict.master.add} Sales`)}
            </h2>
            <p className="mt-3 text-[13px] leading-6 text-slate-500">
              {locale === "id" ? "Master sales dengan identitas, saldo berjalan, dan multi rekening bank." : "Sales master with identity, running balance, and multiple bank accounts."}
            </p>
          </div>
          {editingId ? <button type="button" onClick={resetForm} className="ops-btn-secondary">{dict.common.cancelEdit}</button> : null}
        </div>

        <form className="mt-6 space-y-5" onSubmit={handleSubmit}>
          <div className="grid gap-4 md:grid-cols-2">
            <Field
              label={dict.master.code}
              value={form.code}
              readOnly={!canEditCode}
              placeholder={canEditCode ? "SLS00001" : "Auto"}
              onChange={(value) => setForm((current) => ({ ...current, code: value }))}
            />
            <Field label="Nama" value={form.name} onChange={(value) => setForm((current) => ({ ...current, name: value }))} />
            <SelectField
              label="Jenis identitas"
              value={form.identity_type}
              onChange={(value) => setForm((current) => ({ ...current, identity_type: value as SalesForm["identity_type"] }))}
              options={[
                { value: "KTP", label: "KTP" },
                { value: "SIM", label: "SIM" },
                { value: "PASSPORT", label: "Paspor" }
              ]}
            />
            <Field label="Nomor identitas" value={form.identity_number} onChange={(value) => setForm((current) => ({ ...current, identity_number: value }))} />
            <Field label="Nomor HP" value={form.mobile_phone} onChange={(value) => setForm((current) => ({ ...current, mobile_phone: value }))} />
            <Field label="Email" value={form.email} onChange={(value) => setForm((current) => ({ ...current, email: value }))} />
            <Field label="Tanggal bergabung" type="date" value={form.join_date} onChange={(value) => setForm((current) => ({ ...current, join_date: value }))} />
          </div>

          <label className="block">
            <span className="ops-label">{dict.master.address}</span>
            <textarea value={form.address} onChange={(event) => setForm((current) => ({ ...current, address: event.target.value }))} rows={3} className="ops-textarea" />
          </label>

          <label className="block">
            <span className="ops-label">{dict.common.notes}</span>
            <textarea value={form.notes} onChange={(event) => setForm((current) => ({ ...current, notes: event.target.value }))} rows={3} className="ops-textarea" />
          </label>

          <div className="rounded-lg border border-line/70 bg-slate-50/70 p-4">
            <div className="flex items-center justify-between">
              <h3 className="text-lg font-semibold text-ink">{locale === "id" ? "Daftar rekening bank" : "Bank account list"}</h3>
              <button type="button" onClick={addBankAccount} className="ops-btn-secondary">{locale === "id" ? "Tambah rekening" : "Add account"}</button>
            </div>
            <div className="mt-4 space-y-4">
              {form.bank_accounts.map((account, index) => (
                <div key={index} className="rounded border border-line/70 bg-white p-4">
                  <div className="grid gap-4 md:grid-cols-2">
                    <SelectField
                      label="Bank"
                      value={account.bank_id}
                      onChange={(value) => updateBankAccount(index, { bank_id: value })}
                      options={banks.map((bank) => ({ value: bank.id, label: `${bank.code} - ${bank.name}` }))}
                      placeholder={locale === "id" ? "Pilih bank" : "Choose bank"}
                    />
                    <Field
                      label="Nomor rekening"
                      value={account.account_number}
                      onChange={(value) => updateBankAccount(index, { account_number: value })}
                    />
                  </div>
                  <div className="mt-4 flex justify-end">
                    <button type="button" onClick={() => removeBankAccount(index)} className="ops-btn-danger">
                      {locale === "id" ? "Hapus rekening" : "Remove account"}
                    </button>
                  </div>
                </div>
              ))}
            </div>
          </div>

          {error ? <div className="rounded border border-ember/30 bg-ember/10 px-4 py-3 text-sm text-ember">{error}</div> : null}

          <button type="submit" disabled={submitting} className="ops-btn-primary">
            {submitting ? dict.common.processing : editingId ? (locale === "id" ? `${dict.master.update} sales` : `${dict.master.update} sales`) : (locale === "id" ? `${dict.master.add} sales` : `${dict.master.add} sales`)}
          </button>
        </form>
      </div>

      <div className="ops-table-shell">
        <div className="ops-section-head">
          <div>
            <p className="ops-title">{dict.master.list} Sales</p>
            <p className="ops-subtitle">
              {locale === "id" ? "Master sales dan profil bagi hasil yang siap dipakai di tahap berikutnya." : "Sales master and profit-sharing profiles ready to use in the next stage."}
            </p>
          </div>
          <div className="ops-chip-muted whitespace-nowrap">{salesList.length} data</div>
        </div>
        {!loading && salesList.length > 0 ? (
          <div className="border-t border-line/70 px-6 py-4">
            <label className="block">
              <span className="ops-label">{locale === "id" ? "Cari sales" : "Search sales"}</span>
              <input
                value={search}
                onChange={(event) => setSearch(event.target.value)}
                placeholder={locale === "id" ? "Cari kode, nama, identitas, kontak..." : "Search code, name, identity, contact..."}
                className="ops-input"
              />
            </label>
          </div>
        ) : null}

        {loading ? (
          <div className="px-6 py-8 text-sm text-ink/60">{dict.common.loading}</div>
        ) : salesList.length === 0 ? (
          <div className="px-6 py-8 text-sm text-ink/60">{dict.master.noData}</div>
        ) : filteredSales.length === 0 ? (
          <div className="px-6 py-8 text-sm text-ink/60">{locale === "id" ? "Tidak ada sales yang cocok dengan pencarian." : "No sales match the search."}</div>
        ) : (
          <div className="overflow-x-auto">
            <table className="ops-table">
              <thead>
                <tr>
                  <th>{dict.master.code}</th>
                  <th>{locale === "id" ? "Sales" : "Sales"}</th>
                  <th>{locale === "id" ? "Identitas" : "Identity"}</th>
                  <th>{locale === "id" ? "Rekening bank" : "Bank accounts"}</th>
                  <th>{locale === "id" ? "Saldo komisi" : "Commission balance"}</th>
                  <th>{dict.common.actions}</th>
                </tr>
              </thead>
              <tbody>
                {pagination.pagedItems.map((sales) => (
                  <tr key={sales.id}>
                    <td className="font-semibold text-ink">{sales.code}</td>
                    <td>
                      <div className="font-medium text-ink">{sales.name}</div>
                      <div className="mt-1 text-xs text-slate-500">{sales.mobile_phone || sales.email || "-"}</div>
                    </td>
                    <td>
                      <div className="text-sm font-medium text-ink">{sales.identity_type}</div>
                      <div className="mt-1 text-xs text-slate-500">{sales.identity_number}</div>
                    </td>
                    <td>
                      <div className="space-y-2">
                        {sales.bank_accounts.map((account) => (
                          <div key={account.id} className="text-xs text-slate-600">
                            <div className="font-medium text-ink">{account.bank_code} - {account.bank_name}</div>
                            <div>{account.account_number}</div>
                          </div>
                        ))}
                      </div>
                    </td>
                    <td className="font-medium text-ink">{formatCurrencyAmount(sales.commission_balance, locale, "IDR", 0)}</td>
                    <td>
                      <div className="flex gap-2">
                        <button type="button" onClick={() => void openDetail(sales.id)} className="ops-btn-secondary">{dict.common.detail}</button>
                        <button type="button" onClick={() => startEdit(sales)} className="ops-btn-secondary">{dict.common.edit}</button>
                        <button type="button" onClick={() => void handleDelete(sales.id)} className="ops-btn-danger">{dict.common.delete}</button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
        {!loading && salesList.length > 0 ? (
          <PaginationFooter
            page={pagination.page}
            totalPages={pagination.totalPages}
            rangeStart={pagination.rangeStart}
            rangeEnd={pagination.rangeEnd}
            totalItems={pagination.totalItems}
            itemLabel={locale === "id" ? "sales" : "sales"}
            onPrev={() => pagination.setPage((current) => Math.max(1, current - 1))}
            onNext={() => pagination.setPage((current) => Math.min(pagination.totalPages, current + 1))}
          />
        ) : null}

        <div className="border-t border-line/70 px-6 py-5">
          <div className="flex items-start justify-between gap-4">
            <div>
              <p className="ops-title">Detail komisi sales</p>
              <p className="ops-subtitle">Riwayat komisi sales dari transaksi titip jual yang sudah ditutup.</p>
            </div>
            {selectedSalesDetail ? <div className="ops-chip-muted">{selectedSalesDetail.code}</div> : null}
          </div>

          {detailLoading ? (
            <div className="mt-4 text-sm text-ink/60">{dict.common.loading}</div>
          ) : !selectedSalesDetail ? (
            <div className="mt-4 text-sm text-ink/60">Pilih sales untuk melihat detail komisinya.</div>
          ) : (
            <div className="mt-4 space-y-4">
              <div className="grid gap-4 md:grid-cols-3">
                <div className="rounded-lg border border-line/70 bg-white p-4">
                  <p className="ops-label">Saldo komisi</p>
                  <p className="mt-2 text-2xl font-semibold text-ink">
                    {formatCurrencyAmount(selectedSalesDetail.commission_balance, "id", "IDR", 0)}
                  </p>
                </div>
                <div className="rounded-lg border border-line/70 bg-white p-4">
                  <p className="ops-label">Jumlah titip jual</p>
                  <p className="mt-2 text-xl font-semibold text-ink">{selectedSalesDetail.stats.consignment_count}</p>
                </div>
                <div className="rounded-lg border border-line/70 bg-white p-4">
                  <p className="ops-label">Riwayat komisi</p>
                  <p className="mt-2 text-xl font-semibold text-ink">{selectedSalesDetail.stats.history_count}</p>
                </div>
              </div>

              {selectedSalesDetail.commission_history.length === 0 ? (
                <div className="rounded-lg border border-dashed border-line px-4 py-6 text-sm text-ink/60">
                  Belum ada histori komisi untuk sales ini.
                </div>
              ) : (
                <div className="overflow-x-auto rounded-lg border border-line/70">
                  <table className="ops-table">
                    <thead>
                      <tr>
                        <th>Tanggal</th>
                        <th>Sumber</th>
                        <th>Referensi</th>
                        <th>Arah</th>
                        <th>Nominal</th>
                        <th>Saldo akhir</th>
                      </tr>
                    </thead>
                    <tbody>
                      {selectedSalesDetail.commission_history.slice().reverse().map((entry) => (
                        <tr key={entry.id}>
                          <td className="text-slate-600">
                            {entry.effective_date ?? new Date(entry.occurred_at).toLocaleDateString("id-ID")}
                          </td>
                          <td>
                            <div className="font-medium text-ink">{getSalesHistorySourceLabel(entry.source)}</div>
                            <div className="mt-1 text-xs text-slate-500">{entry.description}</div>
                          </td>
                          <td className="text-slate-600">{entry.reference_no || "-"}</td>
                          <td className="text-slate-600">{entry.direction === "IN" ? "Masuk" : "Keluar"}</td>
                          <td className="font-medium text-ink">{formatCurrencyAmount(entry.amount, "id", "IDR", 0)}</td>
                          <td className="font-medium text-ink">{formatCurrencyAmount(entry.balance_after, "id", "IDR", 0)}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          )}
        </div>
      </div>
    </section>
  );
}

function getSalesHistorySourceLabel(source: SalesDetailRecord["commission_history"][number]["source"]) {
  if (source === "CONSIGNMENT_COMMISSION") return "Komisi titip jual";
  if (source === "MANUAL_ADJUSTMENT") return "Penyesuaian manual";
  return "Saldo pembuka";
}

type FieldProps = {
  label: string;
  value: string;
  onChange: (value: string) => void;
  type?: "text" | "date" | "number";
  readOnly?: boolean;
  placeholder?: string;
};

function Field({ label, value, onChange, type = "text", readOnly = false, placeholder }: FieldProps) {
  return (
    <label className="block">
      <span className="ops-label">{label}</span>
      <input
        type={type}
        value={value}
        readOnly={readOnly}
        placeholder={placeholder}
        onChange={(event) => onChange(event.target.value)}
        className="ops-input"
      />
    </label>
  );
}

type SelectFieldProps = {
  label: string;
  value: string;
  onChange: (value: string) => void;
  options: Array<{ value: string; label: string }>;
  placeholder?: string;
};

function SelectField({ label, value, onChange, options, placeholder }: SelectFieldProps) {
  const { locale } = useLocale();
  return (
    <label className="block">
      <span className="ops-label">{label}</span>
      <select value={value} onChange={(event) => onChange(event.target.value)} className="ops-select">
        <option value="">{placeholder ?? (locale === "id" ? "Pilih opsi" : "Choose option")}</option>
        {options.map((option) => (
          <option key={option.value} value={option.value}>
            {option.label}
          </option>
        ))}
      </select>
    </label>
  );
}
