"use client"

import { useMemo, useState } from "react"
import { Bell, Save, Send, Settings } from "lucide-react"

import { ListPageCard } from "@/app/dashboard/_components"
import { SettingsCard } from "@/components/settings/ui/settings-card"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { XmlApiErrorBanner } from "@/components/xml-apis/shared/xml-api-error-banner"
import type { IdLabelMap, PosReconV2Settings } from "@/components/xml-apis/pos-recon-v2/types"
import { FRONTEND_ROUTES } from "@/config/frontend-routes"
import { dashboardCsrfHeader } from "@/lib/csrf.client"
import { cn } from "@/lib/utils"

type Props = {
  initialSettings: PosReconV2Settings
  corporateDbOptions: IdLabelMap
  bankApiOptions: IdLabelMap
  notifyStatusOptions?: IdLabelMap
  notifyAssetClassOptions?: IdLabelMap
  initialErrorMessage?: string | null
}

const DEFAULT_STATUS_OPTIONS: IdLabelMap = {
  matched: "Matched",
  mismatch: "Mismatch",
  missing_in_oxy: "Missing in Oxy",
  missing_in_xml: "Missing in XML",
  unmapped_customer: "Unmapped customer",
}

function toggleValue(list: string[], value: string, on: boolean): string[] {
  if (on) {
    return list.includes(value) ? list : [...list, value]
  }
  return list.filter((item) => item !== value)
}

function CheckboxGrid({
  options,
  selected,
  onToggle,
  className,
}: {
  options: IdLabelMap
  selected: string[]
  onToggle: (value: string, on: boolean) => void
  className?: string
}) {
  return (
    <div className={cn("grid gap-2 sm:grid-cols-2", className)}>
      {Object.entries(options).map(([value, label]) => {
        const id = `opt-${value}`
        return (
          <label
            key={value}
            htmlFor={id}
            className="flex cursor-pointer items-start gap-2.5 rounded-md border border-transparent px-2 py-1.5 hover:border-border hover:bg-muted/40"
          >
            <Checkbox
              id={id}
              checked={selected.includes(value)}
              onCheckedChange={(checked) => onToggle(value, checked === true)}
              className="mt-0.5"
            />
            <span className="text-sm leading-snug">{label}</span>
          </label>
        )
      })}
    </div>
  )
}

export function PosReconV2SettingsPage({
  initialSettings,
  corporateDbOptions,
  bankApiOptions = {},
  notifyStatusOptions = {},
  notifyAssetClassOptions = {},
  initialErrorMessage = null,
}: Props) {
  const [settings, setSettings] = useState(initialSettings)
  const [selectedBankIds, setSelectedBankIds] = useState<number[]>(
    () => initialSettings.bank_api_ids || []
  )
  const [parentBankIds, setParentBankIds] = useState<Record<string, string>>(() => {
    const map: Record<string, string> = {}
    for (const [id, value] of Object.entries(
      initialSettings.parent_bank_id_by_bank_api || {}
    )) {
      if (value > 0) map[id] = String(value)
    }
    return map
  })
  const [leverageFlip, setLeverageFlip] = useState<Record<string, boolean>>(() => {
    const map: Record<string, boolean> = {}
    for (const [id, value] of Object.entries(
      initialSettings.leverage_sign_flip_by_bank_api || {}
    )) {
      map[id] = value > 0
    }
    return map
  })
  const [message, setMessage] = useState<string | null>(null)
  const [error, setError] = useState(initialErrorMessage)
  const [busy, setBusy] = useState(false)

  const bankRows = useMemo(() => {
    return Object.entries(bankApiOptions)
      .map(([id, label]) => ({ id: Number(id), label }))
      .filter((row) => row.id > 0)
      .sort((a, b) => a.label.localeCompare(b.label))
  }, [bankApiOptions])

  const statusOptions = useMemo(() => {
    return Object.keys(notifyStatusOptions).length > 0
      ? notifyStatusOptions
      : DEFAULT_STATUS_OPTIONS
  }, [notifyStatusOptions])

  const assetClassOptions = useMemo(() => {
    if (Object.keys(notifyAssetClassOptions).length > 0) {
      return notifyAssetClassOptions
    }
    const fromSettings = settings.notify_asset_classes || []
    const map: IdLabelMap = {}
    for (const title of fromSettings) {
      if (title && title !== "__none__") {
        map[title] = title === "__empty__" ? "(Not set)" : title
      }
    }
    return map
  }, [notifyAssetClassOptions, settings.notify_asset_classes])

  const selectedStatusCount = settings.notify_statuses.filter(
    (s) => s && s !== "__none__"
  ).length
  const selectedAssetCount = settings.notify_asset_classes.filter(
    (s) => s && s !== "__none__"
  ).length

  async function persist(sendTest: boolean) {
    setBusy(true)
    setError(null)
    setMessage(null)
    try {
      const res = await fetch(FRONTEND_ROUTES.xmlApis.posReconV2.settingsSubmit, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          ...dashboardCsrfHeader(),
        },
        body: JSON.stringify({
          save: 1,
          send_test: sendTest ? 1 : 0,
          auto_enabled: settings.auto_enabled,
          lookback_days: settings.lookback_days,
          skip_if_run_exists: settings.skip_if_run_exists,
          qty_tolerance: settings.qty_tolerance,
          neglect_zero_qty: settings.neglect_zero_qty,
          corporate_customer_id: settings.corporate_customer_id,
          bank_api_ids: selectedBankIds,
          ignore_xml_asset_types: settings.ignore_xml_asset_types_raw,
          parent_bank_id: Object.fromEntries(
            Object.entries(parentBankIds)
              .map(([id, value]): [string, number] => [id, Number(value) || 0])
              .filter(([, value]) => value > 0)
          ),
          leverage_sign_flip: Object.fromEntries(
            bankRows.map(({ id }) => [String(id), leverageFlip[String(id)] ? 1 : 0])
          ),
          notify_enabled: settings.notify_enabled,
          rocketchat_webhook_url: settings.rocketchat_webhook_url,
          notify_asset_classes: settings.notify_asset_classes,
          notify_statuses: settings.notify_statuses,
        }),
      })
      const json = await res.json().catch(() => ({}))
      if (!res.ok || json.status === "error") {
        setError(json.message || "Save failed.")
        return
      }
      if (json?.data?.settings) {
        const next = json.data.settings
        setSettings((prev) => ({
          ...prev,
          ...next,
          notify_asset_classes: Array.isArray(next.notify_asset_classes)
            ? next.notify_asset_classes
            : prev.notify_asset_classes,
          notify_statuses: Array.isArray(next.notify_statuses)
            ? next.notify_statuses
            : prev.notify_statuses,
          parent_bank_id_by_bank_api: next.parent_bank_id_by_bank_api || {},
          leverage_sign_flip_by_bank_api: next.leverage_sign_flip_by_bank_api || {},
        }))
        if (Array.isArray(next.bank_api_ids)) {
          setSelectedBankIds(next.bank_api_ids.map((id: number) => Number(id)).filter(Boolean))
        }
        const nextParents: Record<string, string> = {}
        for (const [id, value] of Object.entries(next.parent_bank_id_by_bank_api || {})) {
          if (Number(value) > 0) nextParents[id] = String(value)
        }
        setParentBankIds(nextParents)
        const nextLev: Record<string, boolean> = {}
        for (const [id, value] of Object.entries(next.leverage_sign_flip_by_bank_api || {})) {
          nextLev[id] = Number(value) > 0
        }
        setLeverageFlip(nextLev)
      }
      setMessage(json.message || "Settings saved.")
    } finally {
      setBusy(false)
    }
  }

  return (
    <ListPageCard
      icon={Settings}
      title="POS Recon v2 settings"
      description="Cron, matching, and Rocket.Chat alerts for signed-off POS Recon v2 feeds."
      breadcrumb={[
        { label: "XML API" },
        { label: "POS Recon v2", href: "/dashboard/xml-apis/pos-recon-v2" },
        { label: "Settings" },
      ]}
    >
      <XmlApiErrorBanner message={error} />
      {message ? (
        <p className="mb-4 rounded-md border border-emerald-200 bg-emerald-50 px-3 py-2 text-sm text-emerald-800">
          {message}
        </p>
      ) : null}

      <div className="grid w-full gap-6">
        <div className="grid items-start gap-6 xl:grid-cols-2">
          <div className="grid gap-6">
            <SettingsCard
              title="Run & matching"
              description="Cron schedule, quantity rules, and corporate database for Overall Summary."
            >
              <div className="space-y-5">
                <div className="grid gap-3 sm:grid-cols-3">
                  <label className="flex items-start gap-2.5 rounded-md border px-3 py-2.5">
                    <Checkbox
                      checked={Boolean(settings.auto_enabled)}
                      onCheckedChange={(checked) =>
                        setSettings((s) => ({ ...s, auto_enabled: checked === true ? 1 : 0 }))
                      }
                      className="mt-0.5"
                    />
                    <span className="text-sm leading-snug">
                      <span className="font-medium">Auto-enabled</span>
                      <span className="mt-0.5 block text-xs text-muted-foreground">
                        Allow scheduled cron runs
                      </span>
                    </span>
                  </label>
                  <label className="flex items-start gap-2.5 rounded-md border px-3 py-2.5">
                    <Checkbox
                      checked={Boolean(settings.skip_if_run_exists)}
                      onCheckedChange={(checked) =>
                        setSettings((s) => ({
                          ...s,
                          skip_if_run_exists: checked === true ? 1 : 0,
                        }))
                      }
                      className="mt-0.5"
                    />
                    <span className="text-sm leading-snug">
                      <span className="font-medium">Skip if run exists</span>
                      <span className="mt-0.5 block text-xs text-muted-foreground">
                        Skip when a completed run already exists
                      </span>
                    </span>
                  </label>
                  <label className="flex items-start gap-2.5 rounded-md border px-3 py-2.5">
                    <Checkbox
                      checked={Boolean(settings.neglect_zero_qty)}
                      onCheckedChange={(checked) =>
                        setSettings((s) => ({
                          ...s,
                          neglect_zero_qty: checked === true ? 1 : 0,
                        }))
                      }
                      className="mt-0.5"
                    />
                    <span className="text-sm leading-snug">
                      <span className="font-medium">Neglect zero qty</span>
                      <span className="mt-0.5 block text-xs text-muted-foreground">
                        Ignore rows within tolerance of zero
                      </span>
                    </span>
                  </label>
                </div>

                <div className="grid gap-4 sm:grid-cols-2">
                  <div className="space-y-2">
                    <Label htmlFor="lookback_days">Lookback days</Label>
                    <Input
                      id="lookback_days"
                      type="number"
                      min={1}
                      max={30}
                      value={settings.lookback_days ?? 1}
                      onChange={(e) =>
                        setSettings((s) => ({
                          ...s,
                          lookback_days: Number(e.target.value) || 1,
                        }))
                      }
                    />
                  </div>
                  <div className="space-y-2">
                    <Label htmlFor="qty_tolerance">Qty tolerance</Label>
                    <Input
                      id="qty_tolerance"
                      type="number"
                      step="0.01"
                      min={0}
                      value={settings.qty_tolerance ?? 0.01}
                      onChange={(e) =>
                        setSettings((s) => ({
                          ...s,
                          qty_tolerance: Number(e.target.value) || 0.01,
                        }))
                      }
                    />
                  </div>
                </div>

                <div className="space-y-2">
                  <Label>Corporate database</Label>
                  <Select
                    value={
                      settings.corporate_customer_id
                        ? String(settings.corporate_customer_id)
                        : "none"
                    }
                    onValueChange={(value) =>
                      setSettings((s) => ({
                        ...s,
                        corporate_customer_id: value === "none" ? 0 : Number(value) || 0,
                      }))
                    }
                  >
                    <SelectTrigger className="w-full">
                      <SelectValue placeholder="Select corporate DB" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="none">Select corporate DB</SelectItem>
                      {Object.entries(corporateDbOptions).map(([id, label]) => (
                        <SelectItem key={id} value={id}>
                          {label}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              </div>
            </SettingsCard>

            <SettingsCard
              title="Banks"
              description="Leave unchecked to auto-pick signed-off feeds. Parent bank id and leverage sign flip apply per bank API."
            >
              <div className="space-y-3">
                <div className="flex items-center justify-between gap-2">
                  <p className="text-xs text-muted-foreground">
                    Safra, BOS, LGT, UBP, Nomura, CUB, UBS, Swiss Quote when empty.
                  </p>
                  <span className="text-xs text-muted-foreground">
                    {selectedBankIds.length === 0
                      ? "Auto-discover"
                      : `${selectedBankIds.length} selected`}
                  </span>
                </div>

                {bankRows.length === 0 ? (
                  <p className="rounded-md border border-dashed px-3 py-4 text-xs text-muted-foreground">
                    No signed-off bank APIs available.
                  </p>
                ) : (
                  <div className="overflow-hidden rounded-md border">
                    <div className="hidden grid-cols-[minmax(0,1fr)_7.5rem_9rem] gap-2 border-b bg-muted/40 px-3 py-2 text-xs font-medium text-muted-foreground lg:grid">
                      <span>Bank</span>
                      <span>Parent bank id</span>
                      <span>Leverage</span>
                    </div>
                    <div className="max-h-[32rem] divide-y overflow-y-auto">
                      {bankRows.map(({ id, label }) => {
                        const key = String(id)
                        const selected = selectedBankIds.includes(id)
                        return (
                          <div
                            key={id}
                            className="grid grid-cols-1 gap-2 px-3 py-2.5 lg:grid-cols-[minmax(0,1fr)_7.5rem_9rem] lg:items-center"
                          >
                            <label className="flex min-w-0 cursor-pointer items-start gap-2.5">
                              <Checkbox
                                checked={selected}
                                onCheckedChange={(checked) =>
                                  setSelectedBankIds((prev) =>
                                    checked === true
                                      ? prev.includes(id)
                                        ? prev
                                        : [...prev, id]
                                      : prev.filter((value) => value !== id)
                                  )
                                }
                                className="mt-0.5"
                              />
                              <span className="min-w-0 text-sm leading-snug">
                                <span className="font-medium">{label}</span>
                                <span className="ml-1 text-xs text-muted-foreground">
                                  (#{id})
                                </span>
                              </span>
                            </label>
                            <div className="space-y-1 lg:space-y-0">
                              <span className="text-xs text-muted-foreground lg:hidden">
                                Parent bank id
                              </span>
                              <Input
                                type="number"
                                className="h-8 w-full"
                                value={parentBankIds[key] ?? ""}
                                onChange={(e) =>
                                  setParentBankIds((prev) => ({
                                    ...prev,
                                    [key]: e.target.value,
                                  }))
                                }
                              />
                            </div>
                            <label className="flex items-center gap-2 text-sm">
                              <Checkbox
                                checked={Boolean(leverageFlip[key])}
                                onCheckedChange={(checked) =>
                                  setLeverageFlip((prev) => ({
                                    ...prev,
                                    [key]: checked === true,
                                  }))
                                }
                              />
                              Leverage sign flip
                            </label>
                          </div>
                        )
                      })}
                    </div>
                  </div>
                )}
              </div>
            </SettingsCard>
          </div>

          <SettingsCard
            title="Rocket.Chat notifications"
            description="Alert on completed runs when selected statuses and asset classes match."
            className="xl:sticky xl:top-4"
          >
            <div className="space-y-5">
              <label className="flex items-start gap-2.5 rounded-md border px-3 py-2.5">
                <Checkbox
                  checked={Boolean(settings.notify_enabled)}
                  onCheckedChange={(checked) =>
                    setSettings((s) => ({
                      ...s,
                      notify_enabled: checked === true ? 1 : 0,
                    }))
                  }
                  className="mt-0.5"
                />
                <span className="text-sm leading-snug">
                  <span className="inline-flex items-center gap-1.5 font-medium">
                    <Bell className="size-3.5 text-muted-foreground" />
                    Enable notifications on run complete
                  </span>
                  <span className="mt-0.5 block text-xs text-muted-foreground">
                    Sends a summary to Rocket.Chat when a run finishes with alert statuses.
                  </span>
                </span>
              </label>

              <div className="space-y-2">
                <Label htmlFor="rocketchat_webhook_url">Webhook URL override</Label>
                <Input
                  id="rocketchat_webhook_url"
                  type="url"
                  placeholder="Leave empty to use the global system webhook"
                  value={settings.rocketchat_webhook_url ?? ""}
                  onChange={(e) =>
                    setSettings((s) => ({
                      ...s,
                      rocketchat_webhook_url: e.target.value,
                    }))
                  }
                />
              </div>

              <div className="space-y-2">
                <div className="flex items-baseline justify-between gap-2">
                  <Label>Alert statuses</Label>
                  <span className="text-xs text-muted-foreground">
                    {selectedStatusCount} selected
                  </span>
                </div>
                <div className="rounded-md border p-2">
                  <CheckboxGrid
                    options={statusOptions}
                    selected={settings.notify_statuses}
                    onToggle={(value, on) =>
                      setSettings((s) => ({
                        ...s,
                        notify_statuses: toggleValue(s.notify_statuses, value, on),
                      }))
                    }
                  />
                </div>
              </div>

              <div className="space-y-2">
                <div className="flex items-baseline justify-between gap-2">
                  <Label>Asset classes</Label>
                  <span className="text-xs text-muted-foreground">
                    {selectedAssetCount === 0
                      ? "All"
                      : `${selectedAssetCount} selected`}
                  </span>
                </div>
                {Object.keys(assetClassOptions).length === 0 ? (
                  <p className="rounded-md border border-dashed px-3 py-4 text-xs text-muted-foreground">
                    Choose a corporate database and complete a recon run to load asset-class
                    options. Empty selection means all classes.
                  </p>
                ) : (
                  <div className="max-h-[28rem] overflow-y-auto rounded-md border p-2">
                    <CheckboxGrid
                      options={assetClassOptions}
                      selected={settings.notify_asset_classes}
                      onToggle={(value, on) =>
                        setSettings((s) => ({
                          ...s,
                          notify_asset_classes: toggleValue(
                            s.notify_asset_classes,
                            value,
                            on
                          ),
                        }))
                      }
                    />
                  </div>
                )}
                <p className="text-xs text-muted-foreground">
                  Leave all unchecked to include every asset class.
                </p>
              </div>
            </div>
          </SettingsCard>
        </div>

        <div className="sticky bottom-0 z-10 -mx-1 flex flex-wrap gap-2 border-t bg-background/95 px-1 py-3 backdrop-blur">
          <Button type="button" disabled={busy} onClick={() => void persist(false)}>
            <Save className="size-4" />
            {busy ? "Saving…" : "Save settings"}
          </Button>
          <Button
            type="button"
            variant="outline"
            disabled={busy}
            onClick={() => void persist(true)}
          >
            <Send className="size-4" />
            Save &amp; send test
          </Button>
        </div>
      </div>
    </ListPageCard>
  )
}
