"use client";

import { useCallback, useEffect, useState } from "react";
import { CalendarDays, ArrowLeftRight, Wallet, AlertCircle, CheckCircle, ArrowRight } from "lucide-react";
import {
  submitSplitBookingDecision,
  previewSplitBookingOptionPrice,
} from "@/services/refund.service";
import { getMountainRouteDetail } from "@/services/trip.service";
import { formatCurrency } from "@/lib/formatters/currency";
import FormField from "@/components/common/FormField";
import type {
  BookingOptionParticipant,
  BookingOptionPricePreview,
  BookingOptions,
  ParticipantDisposition,
  ParticipantRefundBankData,
} from "@/types/refund";
import type { OpenTrip } from "@/types/trip";
import TargetScheduleCard from "./TargetScheduleCard";
import TripTransferPicker from "./TripTransferPicker";
import styles from "./BookingDecisionForm.module.css";
import splitStyles from "./ParticipantSplitDecisionForm.module.css";

interface Props {
  token: string;
  participants: BookingOptionParticipant[];
  trip: BookingOptions["trip"];
}

const DISPOSITIONS: { code: ParticipantDisposition; label: string; icon: typeof CalendarDays }[] = [
  { code: "REFUND", label: "Refund", icon: Wallet },
  { code: "RESCHEDULE", label: "Pindah Jadwal", icon: CalendarDays },
  { code: "TRIP_TRANSFER", label: "Pindah Trip", icon: ArrowLeftRight },
];

const EMPTY_BANK_DATA: ParticipantRefundBankData = { bank_name: "", account_number: "", account_holder: "" };

export default function ParticipantSplitDecisionForm({ token, participants, trip }: Props) {
  const [assignments, setAssignments] = useState<Record<string, ParticipantDisposition | undefined>>({});
  const [refundBankData, setRefundBankData] = useState<Record<string, ParticipantRefundBankData>>({});
  const [isPending, setIsPending] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [success, setSuccess] = useState(false);

  const refundIds = participants.filter((p) => assignments[p.id] === "REFUND").map((p) => p.id);
  const rescheduleIds = participants.filter((p) => assignments[p.id] === "RESCHEDULE").map((p) => p.id);
  const transferIds = participants.filter((p) => assignments[p.id] === "TRIP_TRANSFER").map((p) => p.id);

  // ── RESCHEDULE bucket: jadwal lain pada gunung & jalur yang sama — SATU tujuan
  //    dipakai bersama untuk semua peserta di bucket ini (lihat catatan render di bawah). ──
  const [rescheduleSchedules, setRescheduleSchedules] = useState<OpenTrip[]>([]);
  const [loadingReschedule, setLoadingReschedule] = useState(false);
  const [rescheduleError, setRescheduleError] = useState<string | null>(null);
  const [selectedRescheduleSchedule, setSelectedRescheduleSchedule] = useState<OpenTrip | null>(null);
  const [reschedulePreview, setReschedulePreview] = useState<BookingOptionPricePreview | null>(null);
  const [loadingReschedulePreview, setLoadingReschedulePreview] = useState(false);

  // ── TRIP_TRANSFER bucket: gunung/jalur/tanggal bebas ─────────────────────
  const [selectedTransferSchedule, setSelectedTransferSchedule] = useState<OpenTrip | null>(null);
  const [transferPreview, setTransferPreview] = useState<BookingOptionPricePreview | null>(null);
  const [loadingTransferPreview, setLoadingTransferPreview] = useState(false);

  const chooseDisposition = useCallback((participantId: string, decision: ParticipantDisposition) => {
    setAssignments((prev) => ({ ...prev, [participantId]: decision }));
    setError(null);
  }, []);

  const updateBankField = useCallback(
    (participantId: string, field: keyof ParticipantRefundBankData, value: string) => {
      setRefundBankData((prev) => ({
        ...prev,
        [participantId]: { ...EMPTY_BANK_DATA, ...prev[participantId], [field]: value },
      }));
      setError(null);
    },
    []
  );

  useEffect(() => {
    if (rescheduleIds.length === 0 || !trip.route_id) {
      setSelectedRescheduleSchedule(null);
      return;
    }
    let cancelled = false;
    setLoadingReschedule(true);
    setRescheduleError(null);
    getMountainRouteDetail(trip.route_id)
      .then((detail) => {
        if (cancelled) return;
        setRescheduleSchedules(detail.available_schedules.filter((s) => s.id !== trip.schedule_id));
      })
      .catch(() => {
        if (!cancelled) setRescheduleError("Gagal memuat daftar jadwal.");
      })
      .finally(() => {
        if (!cancelled) setLoadingReschedule(false);
      });
    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [rescheduleIds.length > 0, trip.route_id, trip.schedule_id]);

  useEffect(() => {
    if (!selectedRescheduleSchedule || rescheduleIds.length === 0) {
      setReschedulePreview(null);
      return;
    }
    let cancelled = false;
    setLoadingReschedulePreview(true);
    previewSplitBookingOptionPrice(token, selectedRescheduleSchedule.id, rescheduleIds)
      .then((preview) => {
        if (!cancelled) setReschedulePreview(preview);
      })
      .catch(() => {
        if (!cancelled) setReschedulePreview(null);
      })
      .finally(() => {
        if (!cancelled) setLoadingReschedulePreview(false);
      });
    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [token, selectedRescheduleSchedule, rescheduleIds.length]);

  useEffect(() => {
    if (!selectedTransferSchedule || transferIds.length === 0) {
      setTransferPreview(null);
      return;
    }
    let cancelled = false;
    setLoadingTransferPreview(true);
    previewSplitBookingOptionPrice(token, selectedTransferSchedule.id, transferIds)
      .then((preview) => {
        if (!cancelled) setTransferPreview(preview);
      })
      .catch(() => {
        if (!cancelled) setTransferPreview(null);
      })
      .finally(() => {
        if (!cancelled) setLoadingTransferPreview(false);
      });
    return () => {
      cancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [token, selectedTransferSchedule, transferIds.length]);

  const isRefundBankDataComplete = (participantId: string) => {
    const data = refundBankData[participantId];
    return !!data && !!data.bank_name.trim() && !!data.account_number.trim() && !!data.account_holder.trim();
  };

  const allDecided = participants.every((p) => assignments[p.id]);
  const canSubmit =
    allDecided &&
    refundIds.every(isRefundBankDataComplete) &&
    (rescheduleIds.length === 0 || !!selectedRescheduleSchedule) &&
    (transferIds.length === 0 || !!selectedTransferSchedule);

  const handleSubmit = () => {
    if (!allDecided) {
      setError("Pilih keputusan untuk setiap peserta terlebih dahulu.");
      return;
    }
    if (!refundIds.every(isRefundBankDataComplete)) {
      setError("Lengkapi data rekening (nama bank, nomor rekening, nama pemilik) untuk setiap peserta yang memilih Refund.");
      return;
    }
    if (rescheduleIds.length > 0 && !selectedRescheduleSchedule) {
      setError("Pilih jadwal tujuan untuk peserta yang pindah jadwal.");
      return;
    }
    if (transferIds.length > 0 && !selectedTransferSchedule) {
      setError("Pilih trip tujuan untuk peserta yang pindah trip.");
      return;
    }
    setError(null);
    setIsPending(true);
    submitSplitBookingDecision(token, {
      assignments: participants.map((p) => {
        const decision = assignments[p.id] as ParticipantDisposition;
        if (decision === "REFUND") {
          const bank = refundBankData[p.id] ?? EMPTY_BANK_DATA;
          return {
            participant_id: p.id,
            decision,
            bank_name: bank.bank_name,
            account_number: bank.account_number,
            account_holder: bank.account_holder,
          };
        }
        return { participant_id: p.id, decision };
      }),
      reschedule_to_trip_schedule_id: selectedRescheduleSchedule?.id,
      trip_transfer_to_trip_schedule_id: selectedTransferSchedule?.id,
    })
      .then(() => setSuccess(true))
      .catch((err) => {
        setError(err instanceof Error ? err.message : "Gagal mengirim keputusan. Coba lagi.");
      })
      .finally(() => setIsPending(false));
  };

  if (success) {
    return (
      <div className={styles.successState}>
        <CheckCircle size={32} className={styles.successIcon} aria-hidden />
        <p className={styles.successText}>
          Keputusan Anda untuk setiap peserta berhasil dikirim. Tim kami akan meninjau dan
          menghubungi Anda melalui WhatsApp untuk proses selanjutnya.
        </p>
      </div>
    );
  }

  return (
    <div className={styles.form}>
      <p className={splitStyles.introNote}>
        Booking ini punya {participants.length} peserta — pilih keputusan untuk masing-masing.
      </p>

      {participants.map((p) => {
        const decision = assignments[p.id];
        const isFirstReschedule = decision === "RESCHEDULE" && rescheduleIds[0] === p.id;
        const isFirstTransfer = decision === "TRIP_TRANSFER" && transferIds[0] === p.id;
        const bank = refundBankData[p.id] ?? EMPTY_BANK_DATA;

        return (
          <div key={p.id} className={splitStyles.participantBlock}>
            <p className={splitStyles.participantName}>{p.name}</p>
            <div className={splitStyles.dispositionRow}>
              {DISPOSITIONS.map((d) => {
                const Icon = d.icon;
                const isSelected = decision === d.code;
                return (
                  <button
                    key={d.code}
                    type="button"
                    onClick={() => chooseDisposition(p.id, d.code)}
                    className={`${splitStyles.dispositionBtn} ${isSelected ? splitStyles.dispositionBtnSelected : ""}`}
                    id={`split-${p.id}-${d.code.toLowerCase()}`}
                    aria-pressed={isSelected}
                  >
                    <span className={splitStyles.dispositionIconWrap} aria-hidden="true">
                      <Icon size={15} />
                    </span>
                    <span>{d.label}</span>
                  </button>
                );
              })}
            </div>

            {decision === "REFUND" && (
              <div className={splitStyles.inlineSection}>
                <FormField
                  label="Nama Bank"
                  required
                  placeholder="cth. BCA, Mandiri, BNI"
                  id={`refund-bank-name-${p.id}`}
                  value={bank.bank_name}
                  onChange={(e) => updateBankField(p.id, "bank_name", e.target.value)}
                />
                <FormField
                  label="Nomor Rekening"
                  required
                  placeholder="Nomor rekening tujuan"
                  id={`refund-account-number-${p.id}`}
                  value={bank.account_number}
                  onChange={(e) => updateBankField(p.id, "account_number", e.target.value)}
                />
                <FormField
                  label="Nama Pemilik Rekening"
                  required
                  placeholder="Sesuai buku tabungan"
                  id={`refund-account-holder-${p.id}`}
                  value={bank.account_holder}
                  onChange={(e) => updateBankField(p.id, "account_holder", e.target.value)}
                />
              </div>
            )}

            {decision === "RESCHEDULE" &&
              (isFirstReschedule ? (
                <div className={styles.targetSection}>
                  <h3 className={styles.targetHeading}>
                    Pilih Tanggal Baru — {trip.mountain} via {trip.route}
                  </h3>
                  {loadingReschedule ? (
                    <p className={styles.loadingText}>Memuat daftar jadwal...</p>
                  ) : rescheduleError ? (
                    <p className={styles.pickerErrorText}>{rescheduleError}</p>
                  ) : rescheduleSchedules.length === 0 ? (
                    <p className={styles.loadingText}>
                      Belum ada jadwal lain yang tersedia untuk gunung dan jalur ini. Silakan hubungi tim kami.
                    </p>
                  ) : (
                    <div className={styles.scheduleList}>
                      {rescheduleSchedules.map((s) => (
                        <TargetScheduleCard
                          key={s.id}
                          schedule={s}
                          selected={selectedRescheduleSchedule?.id === s.id}
                          onSelect={() => setSelectedRescheduleSchedule(s)}
                        />
                      ))}
                    </div>
                  )}
                  {selectedRescheduleSchedule && (
                    <div className={styles.confirmSection}>
                      {loadingReschedulePreview ? (
                        <p className={styles.loadingText}>Menghitung selisih biaya...</p>
                      ) : reschedulePreview ? (
                        <PricePreviewNotice preview={reschedulePreview} styles={styles} />
                      ) : null}
                    </div>
                  )}
                </div>
              ) : (
                <p className={splitStyles.sharedTargetNote}>
                  {selectedRescheduleSchedule
                    ? `Menggunakan jadwal yang sama seperti peserta lain yang memilih Pindah Jadwal: ${selectedRescheduleSchedule.mountain.name} via ${selectedRescheduleSchedule.route.name} — ${selectedRescheduleSchedule.formatted_date}.`
                    : "Pilih jadwal tujuan pada peserta lain yang juga memilih Pindah Jadwal — akan berlaku juga untuk peserta ini."}
                </p>
              ))}

            {decision === "TRIP_TRANSFER" &&
              (isFirstTransfer ? (
                <div className={styles.targetSection}>
                  <h3 className={styles.targetHeading}>Pilih Gunung, Jalur, dan Tanggal Tujuan</h3>
                  <TripTransferPicker
                    excludeScheduleId={trip.schedule_id ?? ""}
                    selectedScheduleId={selectedTransferSchedule?.id ?? null}
                    onSelectSchedule={setSelectedTransferSchedule}
                  />
                  {selectedTransferSchedule && (
                    <div className={styles.confirmSection}>
                      {loadingTransferPreview ? (
                        <p className={styles.loadingText}>Menghitung selisih biaya...</p>
                      ) : transferPreview ? (
                        <PricePreviewNotice preview={transferPreview} styles={styles} />
                      ) : null}
                    </div>
                  )}
                </div>
              ) : (
                <p className={splitStyles.sharedTargetNote}>
                  {selectedTransferSchedule
                    ? `Menggunakan trip tujuan yang sama seperti peserta lain yang memilih Pindah Trip: ${selectedTransferSchedule.mountain.name} via ${selectedTransferSchedule.route.name} — ${selectedTransferSchedule.formatted_date}.`
                    : "Pilih trip tujuan pada peserta lain yang juga memilih Pindah Trip — akan berlaku juga untuk peserta ini."}
                </p>
              ))}
          </div>
        );
      })}

      {error && (
        <div className={styles.errorMsg} role="alert">
          <AlertCircle size={15} aria-hidden />
          <span>{error}</span>
        </div>
      )}

      <button
        type="button"
        onClick={handleSubmit}
        disabled={isPending || !canSubmit}
        suppressHydrationWarning
        className={styles.submitBtn}
        id="split-decision-submit"
      >
        <span>{isPending ? "Memproses..." : "Kirim Keputusan"}</span>
        {!isPending && <ArrowRight size={16} aria-hidden="true" />}
      </button>
    </div>
  );
}

function PricePreviewNotice({
  preview,
  styles,
}: {
  preview: BookingOptionPricePreview;
  styles: Record<string, string>;
}) {
  return (
    <div
      className={`${styles.priceNotice} ${
        preview.direction === "ADDITIONAL_PAYMENT"
          ? styles.priceNoticeWarning
          : preview.direction === "REFUND"
            ? styles.priceNoticeInfo
            : styles.priceNoticeNeutral
      }`}
    >
      {preview.direction === "ADDITIONAL_PAYMENT" && (
        <p>
          Harga tujuan baru <strong>{formatCurrency(preview.new_total)}</strong> — perlu
          pembayaran tambahan <strong>{preview.formatted_difference}</strong>. Invoice akan
          dikirim setelah tim kami menyetujui permintaan ini.
        </p>
      )}
      {preview.direction === "REFUND" && (
        <p>
          Harga tujuan baru <strong>{formatCurrency(preview.new_total)}</strong> — berhak
          menerima refund sebesar <strong>{preview.formatted_difference}</strong> setelah
          disetujui tim kami.
        </p>
      )}
      {preview.direction === "NONE" && <p>Tidak ada perbedaan biaya untuk perpindahan ini.</p>}
    </div>
  );
}
