"use client";

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

import { useLocale } from "@/components/providers/locale-provider";
import { PaginationFooter } from "@/components/shared/pagination-footer";
import type {
  Buyer,
  BuyerContactPersonFormValues,
  BuyerFormValues
} from "@/features/buyers/types/buyer";
import { usePagination } from "@/hooks/use-pagination";
import { useCurrentUser } from "@/hooks/use-current-user";
import type { ApiErrorResponse, DetailResponse } from "@/types/api";
import type { BankRecord } from "@/types/master-data";

const emptyContactPerson: BuyerContactPersonFormValues = {
  name: "",
  mobile_phone: "",
  email: ""
};

const emptyForm: BuyerFormValues = {
  code: "",
  name: "",
  phone: "",
  email: "",
  bank_name: "",
  bank_account_number: "",
  address: "",
  contact_people: [{ ...emptyContactPerson }],
  status: "ACTIVE"
};

export function BuyersClient() {
  const { dict, locale } = useLocale();
  const [buyers, setBuyers] = useState<Buyer[]>([]);
  const [search, setSearch] = useState("");
  const [banks, setBanks] = useState<BankRecord[]>([]);
  const [form, setForm] = useState<BuyerFormValues>(emptyForm);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const { canEditCode } = useCurrentUser();
  const filteredBuyers = useMemo(() => {
    const keyword = search.trim().toLowerCase();
    if (!keyword) return buyers;
    return buyers.filter((buyer) =>
      [
        buyer.code,
        buyer.name,
        buyer.phone ?? "",
        buyer.email ?? "",
        buyer.address ?? "",
        buyer.bank_name ?? "",
        buyer.bank_account_number ?? ""
      ].some((value) => value.toLowerCase().includes(keyword))
    );
  }, [buyers, search]);
  const pagination = usePagination(filteredBuyers, 20);

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

    try {
      const [buyersResponse, banksResponse] = await Promise.all([
        fetch("/api/v1/buyers", { cache: "no-store" }),
        fetch("/api/v1/banks", { cache: "no-store" })
      ]);
      const buyersPayload = (await buyersResponse.json()) as { data: Buyer[] };
      const banksPayload = (await banksResponse.json()) as { data: BankRecord[] };

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

      setBuyers(buyersPayload.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 loadBuyers();
  }, []);

  function startEdit(buyer: Buyer) {
    setEditingId(buyer.id);
    setForm({
      code: buyer.code,
      name: buyer.name,
      phone: buyer.phone ?? "",
      email: buyer.email ?? "",
      bank_name: buyer.bank_name ?? "",
      bank_account_number: buyer.bank_account_number ?? "",
      address: buyer.address ?? "",
      contact_people:
        buyer.contact_people.length > 0
          ? buyer.contact_people.map((contactPerson) => ({
              name: contactPerson.name,
              mobile_phone: contactPerson.mobile_phone ?? "",
              email: contactPerson.email ?? ""
            }))
          : [{ ...emptyContactPerson }],
      status: buyer.status === "INACTIVE" ? "INACTIVE" : "ACTIVE"
    });
    setError(null);
  }

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

  function getBankLabel(bankName: string | null) {
    if (!bankName) return "-";
    const bank = banks.find((item) => item.name === bankName);
    return bank ? `${bank.code} - ${bank.name}` : bankName;
  }

  function updateContactPerson(index: number, field: keyof BuyerContactPersonFormValues, value: string) {
    setForm((current) => ({
      ...current,
      contact_people: current.contact_people.map((contactPerson, contactIndex) =>
        contactIndex === index ? { ...contactPerson, [field]: value } : contactPerson
      )
    }));
  }

  function addContactPerson() {
    setForm((current) => ({
      ...current,
      contact_people: [...current.contact_people, { ...emptyContactPerson }]
    }));
  }

  function removeContactPerson(index: number) {
    setForm((current) => ({
      ...current,
      contact_people:
        current.contact_people.length === 1
          ? [{ ...emptyContactPerson }]
          : current.contact_people.filter((_, contactIndex) => contactIndex !== index)
    }));
  }

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

    const endpoint = editingId ? `/api/v1/buyers/${editingId}` : "/api/v1/buyers";
    const method = editingId ? "PUT" : "POST";

    try {
      const response = await fetch(endpoint, {
        method,
        headers: {
          "Content-Type": "application/json"
        },
        body: JSON.stringify(form)
      });

      const payload = (await response.json()) as DetailResponse<Buyer> | 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 loadBuyers();
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.master.saveError);
    } finally {
      setSubmitting(false);
    }
  }

  async function handleDelete(id: string) {
    const confirmed = window.confirm(`${dict.common.delete} pembeli ini?`);

    if (!confirmed) {
      return;
    }

    setError(null);

    try {
      const response = await fetch(`/api/v1/buyers/${id}`, {
        method: "DELETE"
      });

      if (!response.ok) {
        const payload = (await response.json()) as ApiErrorResponse;
        throw new Error(payload.message);
      }

      if (editingId === id) {
        resetForm();
      }

      await loadBuyers();
    } catch (err) {
      setError(err instanceof Error ? err.message : dict.master.deleteError);
    }
  }

  return (
    <section className="grid gap-6 xl:grid-cols-[0.92fr_1.08fr]">
      <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 ? `${dict.common.edit} Pembeli` : `${dict.master.add} Pembeli`}
            </h2>
          </div>
          {editingId ? (
            <button type="button" onClick={resetForm} className="ops-btn-secondary">{dict.common.cancelEdit}</button>
          ) : null}
        </div>

        <form className="mt-6 space-y-4" onSubmit={handleSubmit}>
          <div className="grid gap-4 md:grid-cols-2">
            <Field
              label={dict.master.code}
              value={form.code}
              readOnly={!canEditCode}
              placeholder={canEditCode ? "CUS00001" : "Auto"}
              onChange={(value) => setForm((current) => ({ ...current, code: value }))}
            />
            <Field
              label={dict.master.name}
              value={form.name}
              onChange={(value) => setForm((current) => ({ ...current, name: value }))}
            />
            <Field
              label="Telepon"
              value={form.phone}
              onChange={(value) => setForm((current) => ({ ...current, phone: value }))}
            />
            <Field
              label="Email"
              value={form.email}
              onChange={(value) => setForm((current) => ({ ...current, email: value }))}
            />
            <label className="block">
              <span className="ops-label">Bank</span>
              <select
                value={form.bank_name}
                onChange={(event) =>
                  setForm((current) => ({ ...current, bank_name: event.target.value }))
                }
                className="ops-select"
              >
                <option value="">{locale === "id" ? "Pilih bank" : "Choose bank"}</option>
                {banks.map((bank) => (
                  <option key={bank.id} value={bank.name}>
                    {bank.code} - {bank.name}
                  </option>
                ))}
              </select>
            </label>
            <Field
              label="No. rekening"
              value={form.bank_account_number}
              onChange={(value) =>
                setForm((current) => ({ ...current, bank_account_number: 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={4}
              className="ops-textarea"
            />
          </label>

          <div className="space-y-3 rounded-[28px] border border-sand-200/80 bg-white/80 p-4">
            <div className="flex items-center justify-between gap-4">
              <div>
                <p className="ops-label">Kontak PIC</p>
                <p className="mt-1 text-sm text-ink/60">
                  Tambahkan satu atau lebih kontak untuk pembeli ini.
                </p>
              </div>
              <button type="button" onClick={addContactPerson} className="ops-btn-secondary">
                Tambah kontak PIC
              </button>
            </div>

            <div className="space-y-3">
              {form.contact_people.map((contactPerson, index) => (
                <div key={`contact-person-${index}`} className="rounded-[24px] border border-sand-200/80 bg-sand-50/80 p-4">
                  <div className="mb-3 flex items-center justify-between gap-3">
                    <p className="text-sm font-semibold text-ink">
                      Kontak PIC {index + 1}
                    </p>
                    <button
                      type="button"
                      onClick={() => removeContactPerson(index)}
                      className="ops-btn-danger"
                    >
                      Hapus
                    </button>
                  </div>

                  <div className="grid gap-4 md:grid-cols-3">
                    <Field
                      label="Nama"
                      value={contactPerson.name}
                      onChange={(value) => updateContactPerson(index, "name", value)}
                    />
                    <Field
                      label="Nomor HP"
                      value={contactPerson.mobile_phone}
                      onChange={(value) => updateContactPerson(index, "mobile_phone", value)}
                    />
                    <Field
                      label="Email"
                      value={contactPerson.email}
                      onChange={(value) => updateContactPerson(index, "email", value)}
                    />
                  </div>
                </div>
              ))}
            </div>
          </div>

          <label className="block">
            <span className="ops-label">{dict.master.status}</span>
            <select
              value={form.status}
              onChange={(event) =>
                setForm((current) => ({
                  ...current,
                  status: event.target.value as BuyerFormValues["status"]
                }))
              }
              className="ops-select"
            >
              <option value="ACTIVE">{dict.master.active}</option>
              <option value="INACTIVE">{dict.master.inactive}</option>
            </select>
          </label>

          {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
                ? `${dict.master.update} buyer`
                : `${dict.master.add} pembeli`}
          </button>
        </form>
      </div>

      <div className="ops-table-shell">
        <div className="ops-section-head">
          <div>
            <p className="ops-title">{dict.master.list} Pembeli</p>
          </div>
          <div className="ops-chip-muted">
            {buyers.length} pembeli
          </div>
        </div>
        {!loading && buyers.length > 0 ? (
          <div className="border-t border-line/70 px-6 py-4">
            <label className="block">
              <span className="ops-label">Cari pembeli</span>
              <input
                value={search}
                onChange={(event) => setSearch(event.target.value)}
                placeholder="Cari code, nama, kontak, bank..."
                className="ops-input"
              />
            </label>
          </div>
        ) : null}

        {loading ? (
          <div className="px-6 py-8 text-sm text-ink/60">{dict.common.loading}</div>
        ) : buyers.length === 0 ? (
          <div className="px-6 py-8 text-sm text-ink/60">
            {dict.master.noData}
          </div>
        ) : filteredBuyers.length === 0 ? (
          <div className="px-6 py-8 text-sm text-ink/60">Tidak ada pembeli yang cocok dengan pencarian.</div>
        ) : (
          <div className="overflow-x-auto">
            <table className="ops-table">
              <thead>
                <tr>
                  <th>{dict.master.code}</th>
                  <th>{dict.master.name}</th>
                  <th>Kontak</th>
                  <th>Kontak PIC</th>
                  <th>Pembayaran</th>
                  <th>{dict.master.status}</th>
                  <th>{dict.common.actions}</th>
                </tr>
              </thead>
              <tbody>
                {pagination.pagedItems.map((buyer) => (
                  <tr key={buyer.id}>
                    <td className="font-semibold text-ink">{buyer.code}</td>
                    <td>
                      <div className="font-medium text-ink">{buyer.name}</div>
                      {buyer.address ? (
                        <div className="mt-1 max-w-xs text-xs leading-5 text-ink/55">
                          {buyer.address}
                        </div>
                      ) : null}
                    </td>
                    <td className="text-slate-600">
                      <div>{buyer.phone || "-"}</div>
                      <div className="mt-1 text-xs">{buyer.email || "-"}</div>
                    </td>
                    <td className="text-slate-600">
                      {buyer.contact_people.length === 0 ? (
                        <div>-</div>
                      ) : (
                        <div className="space-y-2">
                          {buyer.contact_people.map((contactPerson) => (
                            <div key={contactPerson.id} className="text-xs leading-5">
                              <div className="font-medium text-ink">{contactPerson.name}</div>
                              <div>{contactPerson.mobile_phone || "-"}</div>
                              <div>{contactPerson.email || "-"}</div>
                            </div>
                          ))}
                        </div>
                      )}
                    </td>
                    <td className="text-slate-600">
                      <div>{getBankLabel(buyer.bank_name)}</div>
                      <div className="mt-1 text-xs">
                        {buyer.bank_account_number || "-"}
                      </div>
                    </td>
                    <td>
                      <span className={buyer.status === "INACTIVE" ? "ops-chip-danger" : "ops-chip-active"}>
                        {buyer.status === "INACTIVE" ? dict.master.inactive : dict.master.active}
                      </span>
                    </td>
                    <td>
                      <div className="flex gap-2">
                        <button type="button" onClick={() => startEdit(buyer)} className="ops-btn-secondary">{dict.common.edit}</button>
                        <button type="button" onClick={() => void handleDelete(buyer.id)} className="ops-btn-danger">{dict.common.delete}</button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
        {!loading && buyers.length > 0 ? (
          <PaginationFooter
            page={pagination.page}
            totalPages={pagination.totalPages}
            rangeStart={pagination.rangeStart}
            rangeEnd={pagination.rangeEnd}
            totalItems={pagination.totalItems}
            itemLabel="pembeli"
            onPrev={() => pagination.setPage((current) => Math.max(1, current - 1))}
            onNext={() => pagination.setPage((current) => Math.min(pagination.totalPages, current + 1))}
          />
        ) : null}
      </div>
    </section>
  );
}

type FieldProps = {
  label: string;
  value: string;
  onChange: (value: string) => void;
  readOnly?: boolean;
  placeholder?: string;
};

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