"use client";

import Link from "next/link";
import { FormEvent, useEffect, useRef, useState } from "react";
import {
  Branch,
  Service,
  Tenant,
  Ticket,
  createTicket,
  getBranchServices,
  getBranches,
  getTenant,
  getTicketsForDevice,
} from "@/lib/api";
import { getDeviceToken } from "@/lib/device";

type Step = "tenant" | "branch" | "service" | "ticket";

type Props = {
  initialTenantCode?: string;
  initialBranchId?: number;
};

function pickLatestTicket(
  tickets: Ticket[],
  branchId?: number
): Ticket | null {
  const scoped =
    branchId != null
      ? tickets.filter((item) => item.branch.id === branchId)
      : tickets;
  if (scoped.length === 0) {
    return null;
  }

  return [...scoped].sort(
    (a, b) =>
      new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
  )[0];
}

export default function CustomerTicketFlow({
  initialTenantCode,
  initialBranchId,
}: Props) {
  const fromQr =
    initialTenantCode != null &&
    initialTenantCode !== "" &&
    initialBranchId != null &&
    Number.isFinite(initialBranchId);

  const [step, setStep] = useState<Step>(fromQr ? "service" : "tenant");
  const [tenantCode, setTenantCode] = useState(
    initialTenantCode?.trim().toUpperCase() ?? ""
  );
  const [tenant, setTenant] = useState<Tenant | null>(null);
  const [branches, setBranches] = useState<Branch[]>([]);
  const [services, setServices] = useState<Service[]>([]);
  const [selectedBranch, setSelectedBranch] = useState<Branch | null>(null);
  const [ticket, setTicket] = useState<Ticket | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const bootstrapped = useRef(false);

  useEffect(() => {
    if (bootstrapped.current) return;
    bootstrapped.current = true;

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

      try {
        const deviceToken = getDeviceToken();
        if (deviceToken) {
          const responses = await getTicketsForDevice(deviceToken);
          const latest = pickLatestTicket(
            responses.map((response) => response.ticket),
            fromQr ? initialBranchId : undefined
          );
          if (latest) {
            setTicket(latest);
            setSelectedBranch({
              id: latest.branch.id,
              name: latest.branch.name,
              tellerStations: latest.branch.tellerStations ?? [],
            });
            setStep("ticket");
            setLoading(false);
            return;
          }
        }
      } catch {
        // No saved ticket — continue into the normal flow.
      }

      if (!fromQr) {
        setLoading(false);
        return;
      }

      const code = initialTenantCode!.trim().toUpperCase();
      const branchId = initialBranchId!;

      try {
        const [tenantData, branchData] = await Promise.all([
          getTenant(code),
          getBranches(code),
        ]);
        const branch = branchData.find((item) => item.id === branchId);
        if (!branch) {
          setError(
            "This branch was not found. Scan the QR again or enter a company code."
          );
          setTenant(tenantData);
          setBranches(branchData);
          setTenantCode(code);
          setStep("branch");
          return;
        }

        const branchServices = await getBranchServices(code, branch.id);
        setTenant(tenantData);
        setBranches(branchData);
        setTenantCode(code);
        setSelectedBranch(branch);
        setServices(branchServices);
        setStep("service");
      } catch {
        setError(
          "Could not open this branch link. Scan the QR again or enter a company code."
        );
        setStep("tenant");
      } finally {
        setLoading(false);
      }
    }

    void bootstrap();
  }, [fromQr, initialTenantCode, initialBranchId]);

  async function handleTenantSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const code = tenantCode.trim().toUpperCase();
    if (!code) {
      setError("Enter a company code.");
      return;
    }

    setLoading(true);
    setError(null);

    try {
      const [tenantData, branchData] = await Promise.all([
        getTenant(code),
        getBranches(code),
      ]);
      setTenant(tenantData);
      setBranches(branchData);
      setTenantCode(code);
      setStep("branch");
    } catch {
      setError("Could not find that company. Check the code and try again.");
    } finally {
      setLoading(false);
    }
  }

  async function handleSelectBranch(branch: Branch) {
    if (!tenant) return;

    setLoading(true);
    setError(null);
    setSelectedBranch(branch);

    try {
      const branchServices = await getBranchServices(tenant.code, branch.id);
      setServices(branchServices);
      setStep("service");
    } catch {
      setError("Could not load services for this branch.");
    } finally {
      setLoading(false);
    }
  }

  async function handleSelectService(service: Service) {
    if (!selectedBranch) return;

    setLoading(true);
    setError(null);

    try {
      const response = await createTicket({
        branchId: selectedBranch.id,
        serviceId: service.id,
        deviceToken: getDeviceToken(),
      });
      setTicket(response.ticket);
      setSelectedBranch(response.ticket.branch);
      setStep("ticket");
    } catch {
      setError(
        "Could not get a ticket number. Make sure this branch has services assigned."
      );
    } finally {
      setLoading(false);
    }
  }

  async function resetFlow() {
    setTicket(null);
    setError(null);

    if (fromQr && initialTenantCode && initialBranchId != null) {
      setLoading(true);
      try {
        const code = initialTenantCode.trim().toUpperCase();
        const [tenantData, branchData] = await Promise.all([
          getTenant(code),
          getBranches(code),
        ]);
        const branch = branchData.find((item) => item.id === initialBranchId);
        if (!branch) {
          setTenant(tenantData);
          setBranches(branchData);
          setTenantCode(code);
          setStep("branch");
          return;
        }
        const branchServices = await getBranchServices(code, branch.id);
        setTenant(tenantData);
        setBranches(branchData);
        setTenantCode(code);
        setSelectedBranch(branch);
        setServices(branchServices);
        setStep("service");
      } catch {
        setError("Could not reload services. Try scanning the QR again.");
        setStep("tenant");
      } finally {
        setLoading(false);
      }
      return;
    }

    if (selectedBranch && tenant) {
      setLoading(true);
      try {
        const branchServices = await getBranchServices(
          tenant.code,
          selectedBranch.id
        );
        setServices(branchServices);
        setStep("service");
      } catch {
        setError("Could not load services for this branch.");
        setStep("branch");
      } finally {
        setLoading(false);
      }
      return;
    }

    setStep(tenant ? "branch" : "tenant");
  }

  function startOver() {
    setStep("tenant");
    setTenantCode("");
    setTenant(null);
    setBranches([]);
    setSelectedBranch(null);
    setServices([]);
    setTicket(null);
    setError(null);
  }

  const welcomeCopy = fromQr
    ? "Pilih perkhidmatan untuk mendapatkan nombor."
    : "Imbas QR code di branch anda, atau masukkan kod syarikat di bawah.";

  return (
    <main className="mx-auto flex min-h-full w-full max-w-xl flex-col gap-8 px-6 py-12">
      <header className="space-y-2">
        <p className="text-sm tracking-wide text-zinc-500 uppercase">
          Sistem Nombor Giliran
        </p>
        <h1 className="text-3xl font-semibold tracking-tight text-zinc-900">
          {tenant?.name ?? "Dapatkan tiket"}
        </h1>
        <p className="text-base text-zinc-600">
          {tenant?.welcomeMessage ?? welcomeCopy}
        </p>
      </header>

      {error ? (
        <p className="rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
          {error}
        </p>
      ) : null}

      {fromQr && loading && step === "service" && !selectedBranch ? (
        <p className="text-sm text-zinc-600">Loading perkhidmatan branch…</p>
      ) : null}

      {step === "tenant" ? (
        <form onSubmit={handleTenantSubmit} className="space-y-4">
          <label className="block space-y-2">
            <span className="text-sm font-medium text-zinc-700">
              Kod syarikat
            </span>
            <input
              value={tenantCode}
              onChange={(event) => setTenantCode(event.target.value)}
              className="w-full rounded-md border border-zinc-300 bg-white px-3 py-2 text-zinc-900 outline-none focus:border-zinc-900"
              placeholder="Kod syarikat"
              autoComplete="off"
              disabled={loading}
            />
          </label>
          <button
            type="submit"
            disabled={loading || !tenantCode.trim()}
            className="w-full rounded-md bg-zinc-900 px-4 py-3 text-sm font-medium text-white disabled:opacity-60"
          >
            {loading ? "Loading…" : "Lanjutkan"}
          </button>
        </form>
      ) : null}

      {step === "branch" ? (
        <section className="space-y-4">
          <div className="flex items-center justify-between gap-3">
            <h2 className="text-lg font-medium text-zinc-900">Choose a branch</h2>
            <button
              type="button"
              onClick={startOver}
              className="text-sm text-zinc-500 underline-offset-2 hover:underline"
            >
              Change company
            </button>
          </div>
          {branches.length === 0 ? (
            <p className="text-sm text-zinc-600">No branches available.</p>
          ) : (
            <ul className="space-y-2">
              {branches.map((branch) => (
                <li key={branch.id}>
                  <button
                    type="button"
                    disabled={loading}
                    onClick={() => handleSelectBranch(branch)}
                    className="flex w-full items-center justify-between rounded-md border border-zinc-200 bg-white px-4 py-3 text-left text-zinc-900 transition hover:border-zinc-400 disabled:opacity-60"
                  >
                    <span>{branch.name}</span>
                    <span className="text-zinc-400">→</span>
                  </button>
                </li>
              ))}
            </ul>
          )}
        </section>
      ) : null}

      {step === "service" && selectedBranch ? (
        <section className="space-y-4">
          <div className="flex items-center justify-between gap-3">
            <h2 className="text-lg font-medium text-zinc-900">
              Perkhidmatan di Cawangan {selectedBranch.name}
            </h2>
            {fromQr ? (
              <Link
                href="/"
                className="text-sm text-zinc-500 underline-offset-2 hover:underline"
              >
                Masukkan kod perkhidmatan
              </Link>
            ) : (
              <button
                type="button"
                onClick={() => {
                  setStep("branch");
                  setSelectedBranch(null);
                  setServices([]);
                  setError(null);
                }}
                className="text-sm text-zinc-500 underline-offset-2 hover:underline"
              >
                Kembali
              </button>
            )}
          </div>
          {services.length === 0 ? (
            <p className="text-sm text-zinc-600">
              Tiada perkhidmatan yang ditugaskan kepada branch ini. Hubungkan
              perkhidmatan melalui grup branch dalam aplikasi admin, kemudian
              cuba lagi.
            </p>
          ) : (
            <ul className="space-y-2">
              {services.map((service) => (
                <li key={service.id}>
                  <button
                    type="button"
                    disabled={loading}
                    onClick={() => handleSelectService(service)}
                    className="flex w-full items-center justify-between rounded-md border border-zinc-200 bg-white px-4 py-3 text-left text-zinc-900 transition hover:border-zinc-400 disabled:opacity-60"
                  >
                    <span>{service.name}</span>
                    <span className="text-sm text-zinc-500">
                      {loading ? "…" : "Dapatkan nombor"}
                    </span>
                  </button>
                </li>
              ))}
            </ul>
          )}
        </section>
      ) : null}

      {step === "ticket" && ticket ? (
        <section className="space-y-6 rounded-md border border-zinc-200 bg-white px-6 py-8 text-center">
          <p className="text-sm tracking-wide text-zinc-500 uppercase">
            Nombor tiket anda
          </p>
          <p className="text-6xl font-semibold tracking-tight text-zinc-900">
            {ticket.number}
          </p>
          <div className="space-y-1 text-sm text-zinc-600">
            <p>{ticket.service.name}</p>
            <p>{ticket.branch.name}</p>
          </div>
          <button
            type="button"
            onClick={resetFlow}
            className="w-full rounded-md bg-zinc-900 px-4 py-3 text-sm font-medium text-white"
          >
            Dapatkan tiket lain
          </button>
        </section>
      ) : null}
    </main>
  );
}
