"use client";

import { useRouter } from "next/navigation";
import { useMemo, useState, useTransition } from "react";
import { Button } from "@/components/ui/Button";
import { Card, CardHeader, CardTitle, Field, Label } from "@/components/ui/Card";
import { Input } from "@/components/ui/Input";
import { Select } from "@/components/ui/Select";
import { StatCard } from "@/components/shared/StatCard";
import {
  AuthorizationStatusBadge,
  EligibilityStatusBadge,
} from "@/components/features/elections/AuthorizationStatusBadge";
import { generateVoterRoll } from "@/lib/actions/ballots";
import {
  createVotingEntity,
  importVotingEntitiesFromCsv,
} from "@/lib/actions/voting-entities";
import {
  reviewAuthorizationRecord,
  upsertAuthorizationRecord,
} from "@/lib/actions/authorization-records";
import {
  ELIGIBILITY_MODEL_LABELS,
  VOTING_ENTITY_TYPE_LABELS,
} from "@/config/elections";
import { formatNumber } from "@/lib/utils/format";
import type {
  VoterRollRow,
  VoterRollSummary,
} from "@/lib/queries/voter-roll-queries";
import type {
  EligibilityModel,
  EligibilityStatus,
  ElectionStatus,
  VotingEntityType,
} from "@/types";

interface ContactOption {
  id: string;
  name: string;
  email: string;
}

interface VotingEntityOption {
  id: string;
  label: string;
  entityType: VotingEntityType;
  ownerCount: number;
  owners: {
    contactId: string;
    name: string;
    email: string;
    isPrimary: boolean;
  }[];
  latestAuthorizationStatus: string | null;
}

interface VoterRollPanelProps {
  electionId: string;
  electionStatus: ElectionStatus;
  eligibilityModel: EligibilityModel;
  requiresAuthorizationRecord: boolean;
  openEnrollment?: boolean;
  rows: VoterRollRow[];
  summary: VoterRollSummary;
  contacts: ContactOption[];
  votingEntities: VotingEntityOption[];
  readOnly?: boolean;
}

export function VoterRollPanel({
  electionId,
  electionStatus,
  eligibilityModel,
  requiresAuthorizationRecord,
  openEnrollment,
  rows,
  summary,
  contacts,
  votingEntities,
  readOnly,
}: VoterRollPanelProps) {
  const router = useRouter();
  const [error, setError] = useState<string | null>(null);
  const [message, setMessage] = useState<string | null>(null);
  const [isPending, startTransition] = useTransition();
  const [filter, setFilter] = useState<EligibilityStatus | "all">("all");
  const [search, setSearch] = useState("");

  const [entityLabel, setEntityLabel] = useState("");
  const [entityType, setEntityType] = useState<VotingEntityType>(
    eligibilityModel === "shareholder"
      ? "shareholder_account"
      : eligibilityModel === "custom"
        ? "custom"
        : "property_unit"
  );
  const [ownerIds, setOwnerIds] = useState<string[]>([]);
  const [weight, setWeight] = useState("1");
  const [importRaw, setImportRaw] = useState("");

  const [authEntityId, setAuthEntityId] = useState("");
  const [designatedVoterId, setDesignatedVoterId] = useState("");
  const [rejectReason, setRejectReason] = useState("");

  const filteredRows = useMemo(() => {
    const term = search.trim().toLowerCase();
    return rows.filter((row) => {
      if (filter !== "all" && row.eligibilityStatus !== filter) return false;
      if (!term) return true;
      return (
        row.label.toLowerCase().includes(term) ||
        (row.secondaryLabel?.toLowerCase().includes(term) ?? false)
      );
    });
  }, [rows, filter, search]);

  const authEntity = votingEntities.find((entity) => entity.id === authEntityId);

  function run(
    action: () => Promise<
      | { success: true; data?: unknown }
      | { success: false; error: string }
    >,
    successMessage?: string
  ) {
    setError(null);
    setMessage(null);
    startTransition(async () => {
      const result = await action();
      if (!result.success) {
        setError(result.error);
        return;
      }
      if (successMessage) setMessage(successMessage);
      router.refresh();
    });
  }

  function toggleOwner(contactId: string) {
    setOwnerIds((current) =>
      current.includes(contactId)
        ? current.filter((id) => id !== contactId)
        : [...current, contactId]
    );
  }

  return (
    <div className="space-y-5">
      <div className="grid gap-3 sm:grid-cols-2 xl:grid-cols-5">
        <StatCard label="On roll" value={formatNumber(summary.total)} />
        <StatCard label="Eligible" value={formatNumber(summary.eligible)} />
        <StatCard
          label="Pending auth"
          value={formatNumber(summary.pendingAuthorization)}
        />
        <StatCard label="Blocked" value={formatNumber(summary.blocked)} />
        <StatCard label="Voted" value={formatNumber(summary.voted)} />
      </div>

      <Card className="px-5 py-4">
        <p className="text-[13px] font-semibold">
          {ELIGIBILITY_MODEL_LABELS[eligibilityModel]}
          {eligibilityModel === "member"
            ? openEnrollment
              ? " · Open vote"
              : " · Email / voter roll"
            : ""}
        </p>
        <p className="mt-1 text-[12px] text-muted">
          {eligibilityModel === "member" && openEnrollment
            ? "Open vote is on — anyone with the ballot link can verify and vote. Voters appear here as they enroll. You can still regenerate from Audience contacts."
            : eligibilityModel === "member"
              ? "Email / voter roll mode — only contacts on this roll can vote. Snapshot from Audience as of the record date, or regenerate anytime before certification."
              : "Roll is snapshotted from voting entities as of the record date."}
          {requiresAuthorizationRecord
            ? " Multi-owner entities require a valid authorization record."
            : ""}
        </p>
        {!readOnly && electionStatus !== "certified" && (
          <div className="mt-3">
            <Button
              type="button"
              size="sm"
              loading={isPending}
              onClick={() =>
                run(async () => {
                  const result = await generateVoterRoll(electionId);
                  if (!result.success) return result;
                  return { success: true, data: result.data };
                }, "Voter roll regenerated from the current snapshot")
              }
            >
              Regenerate voter roll
            </Button>
            <p className="mt-1.5 text-[11px] text-muted">
              {openEnrollment
                ? "Optional — pulls Audience contacts onto this roll while live."
                : "Pulls current Audience contacts onto this roll (works while live)."}
            </p>
          </div>
        )}
      </Card>

      {eligibilityModel !== "member" && (
        <div className="grid gap-4 lg:grid-cols-2">
          <Card className="p-5">
            <CardHeader className="mb-3 px-0 py-0">
              <CardTitle>Add voting entity</CardTitle>
            </CardHeader>
            <div className="space-y-3">
              <Field>
                <Label>Label</Label>
                <Input
                  value={entityLabel}
                  onChange={(event) => setEntityLabel(event.target.value)}
                  placeholder="Unit 101"
                />
              </Field>
              <Field>
                <Label>Entity type</Label>
                <Select
                  value={entityType}
                  onChange={(event) =>
                    setEntityType(event.target.value as VotingEntityType)
                  }
                >
                  {Object.entries(VOTING_ENTITY_TYPE_LABELS).map(
                    ([value, label]) => (
                      <option key={value} value={value}>
                        {label}
                      </option>
                    )
                  )}
                </Select>
              </Field>
              <Field>
                <Label>Weight / shares</Label>
                <Input
                  type="number"
                  min={0.0001}
                  step="0.0001"
                  value={weight}
                  onChange={(event) => setWeight(event.target.value)}
                />
              </Field>
              <div>
                <p className="mb-2 text-[12px] font-semibold text-muted">
                  Owners
                </p>
                <div className="max-h-40 space-y-1 overflow-y-auto rounded-lg border border-border p-2">
                  {contacts.map((contact) => (
                    <label
                      key={contact.id}
                      className="flex cursor-pointer items-center gap-2 rounded px-2 py-1 text-[12.5px] hover:bg-[#F8FAFC]"
                    >
                      <input
                        type="checkbox"
                        checked={ownerIds.includes(contact.id)}
                        onChange={() => toggleOwner(contact.id)}
                      />
                      <span>
                        {contact.name}{" "}
                        <span className="text-muted">({contact.email})</span>
                      </span>
                    </label>
                  ))}
                </div>
              </div>
              <Button
                type="button"
                loading={isPending}
                onClick={() => {
                  if (!entityLabel.trim() || ownerIds.length === 0) {
                    setError("Label and at least one owner are required");
                    return;
                  }
                  run(
                    () =>
                      createVotingEntity({
                        label: entityLabel.trim(),
                        entityType,
                        ownerContactIds: ownerIds,
                        primaryOwnerContactId: ownerIds[0],
                        metadata: { weight: Number(weight) || 1 },
                      }),
                    "Voting entity created"
                  );
                  setEntityLabel("");
                  setOwnerIds([]);
                }}
              >
                Create entity
              </Button>
            </div>
          </Card>

          <Card className="p-5">
            <CardHeader className="mb-3 px-0 py-0">
              <CardTitle>Import entities</CardTitle>
            </CardHeader>
            <p className="mb-2 text-[12px] text-muted">
              One row per line: label, entityType, ownerEmail[, weight]
            </p>
            <textarea
              className="min-h-[140px] w-full rounded-lg border border-border px-3 py-2 text-[13px]"
              value={importRaw}
              onChange={(event) => setImportRaw(event.target.value)}
              placeholder="Unit 305,property_unit,alex.rivera@example.com,1"
            />
            <Button
              type="button"
              className="mt-3"
              variant="outline"
              loading={isPending}
              onClick={() =>
                run(
                  () => importVotingEntitiesFromCsv({ raw: importRaw }),
                  "Import finished"
                )
              }
            >
              Import CSV text
            </Button>
          </Card>

          <Card className="p-5 lg:col-span-2">
            <CardHeader className="mb-3 px-0 py-0">
              <CardTitle>Authorization records</CardTitle>
            </CardHeader>
            <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
              <Field>
                <Label>Entity</Label>
                <Select
                  value={authEntityId}
                  onChange={(event) => {
                    setAuthEntityId(event.target.value);
                    setDesignatedVoterId("");
                  }}
                >
                  <option value="">Select entity</option>
                  {votingEntities.map((entity) => (
                    <option key={entity.id} value={entity.id}>
                      {entity.label} ({entity.ownerCount} owners)
                    </option>
                  ))}
                </Select>
              </Field>
              <Field>
                <Label>Designated voter</Label>
                <Select
                  value={designatedVoterId}
                  onChange={(event) => setDesignatedVoterId(event.target.value)}
                >
                  <option value="">Select owner</option>
                  {authEntity?.owners.map((owner) => (
                    <option key={owner.contactId} value={owner.contactId}>
                      {owner.name}
                    </option>
                  ))}
                </Select>
              </Field>
              <Field>
                <Label>Reject reason</Label>
                <Input
                  value={rejectReason}
                  onChange={(event) => setRejectReason(event.target.value)}
                  placeholder="Required when rejecting"
                />
              </Field>
            </div>
            <div className="mt-3 flex flex-wrap gap-2">
              <Button
                type="button"
                size="sm"
                loading={isPending}
                disabled={!authEntityId || !designatedVoterId}
                onClick={() =>
                  run(
                    () =>
                      upsertAuthorizationRecord({
                        votingEntityId: authEntityId,
                        designatedVoterContactId: designatedVoterId,
                        status: "valid",
                        effectiveDate: new Date().toISOString().slice(0, 10),
                      }),
                    "Authorization filed as valid"
                  )
                }
              >
                File valid record
              </Button>
              <Button
                type="button"
                size="sm"
                variant="outline"
                loading={isPending}
                disabled={!authEntityId}
                onClick={() =>
                  run(
                    () =>
                      reviewAuthorizationRecord({
                        votingEntityId: authEntityId,
                        decision: "approve",
                        designatedVoterContactId: designatedVoterId || null,
                        effectiveDate: new Date().toISOString().slice(0, 10),
                      }),
                    "Authorization approved"
                  )
                }
              >
                Approve
              </Button>
              <Button
                type="button"
                size="sm"
                variant="outline"
                loading={isPending}
                disabled={!authEntityId}
                onClick={() =>
                  run(
                    () =>
                      reviewAuthorizationRecord({
                        votingEntityId: authEntityId,
                        decision: "reject",
                        rejectionReason: rejectReason,
                      }),
                    "Authorization rejected"
                  )
                }
              >
                Reject
              </Button>
            </div>
          </Card>
        </div>
      )}

      <Card className="overflow-hidden">
        <div className="flex flex-wrap items-end gap-3 border-b border-border px-5 py-4">
          <Field className="min-w-[200px]">
            <Label>Search</Label>
            <Input
              value={search}
              onChange={(event) => setSearch(event.target.value)}
              placeholder="Name, email, or label"
            />
          </Field>
          <Field>
            <Label>Eligibility</Label>
            <Select
              value={filter}
              onChange={(event) =>
                setFilter(event.target.value as EligibilityStatus | "all")
              }
            >
              <option value="all">All</option>
              <option value="eligible">Eligible</option>
              <option value="pending_authorization">Pending authorization</option>
              <option value="blocked">Blocked</option>
            </Select>
          </Field>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full min-w-[720px] text-left text-[13px]">
            <thead className="bg-[#F8FAFC] text-[11px] uppercase tracking-wide text-muted">
              <tr>
                <th className="px-4 py-3 font-bold">Voter</th>
                <th className="px-4 py-3 font-bold">Type</th>
                <th className="px-4 py-3 font-bold">Weight</th>
                <th className="px-4 py-3 font-bold">Eligibility</th>
                <th className="px-4 py-3 font-bold">Authorization</th>
                <th className="px-4 py-3 font-bold">Voted</th>
              </tr>
            </thead>
            <tbody>
              {filteredRows.length === 0 ? (
                <tr>
                  <td colSpan={6} className="px-4 py-8 text-center text-muted">
                    No voters on the roll yet. Publish or regenerate to snapshot
                    eligibility.
                  </td>
                </tr>
              ) : (
                filteredRows.map((row) => (
                  <tr key={row.id} className="border-t border-border">
                    <td className="px-4 py-3">
                      <p className="font-semibold">{row.label}</p>
                      <p className="text-[12px] text-muted">
                        {row.secondaryLabel ?? "—"}
                        {row.designatedVoterName
                          ? ` · voter: ${row.designatedVoterName}`
                          : ""}
                      </p>
                    </td>
                    <td className="px-4 py-3 capitalize">
                      {row.voterType.replace("_", " ")}
                    </td>
                    <td className="px-4 py-3">{row.weight}</td>
                    <td className="px-4 py-3">
                      <EligibilityStatusBadge status={row.eligibilityStatus} />
                    </td>
                    <td className="px-4 py-3">
                      <AuthorizationStatusBadge
                        status={row.authorizationStatus}
                      />
                    </td>
                    <td className="px-4 py-3">
                      {row.hasVoted ? "Yes" : "No"}
                    </td>
                  </tr>
                ))
              )}
            </tbody>
          </table>
        </div>
      </Card>

      {error && (
        <p className="rounded-md bg-danger-bg px-3 py-2 text-[13px] text-danger">
          {error}
        </p>
      )}
      {message && (
        <p className="rounded-md bg-success-bg px-3 py-2 text-[13px] text-success">
          {message}
        </p>
      )}
    </div>
  );
}
