import { useCallback, useEffect, useMemo, useState } from 'react'
import { Link } from 'react-router-dom'
import { api, ApiError } from '../api/client'
import { ScheduleFrequencyPicker } from '../components/ScheduleFrequencyPicker'
import {
  Button,
  Card,
  ErrorText,
  Field,
  Notice,
  PageTitle,
  Select,
  StatusBadge,
  TableEmpty,
} from '../components/ui'
import { formatUnixNano } from '../lib/formatDate'
import {
  buildCronFromFrequency,
  defaultScheduleFrequency,
  describeCron,
  frequencyFromCron,
  type ScheduleFrequency,
} from '../lib/scheduleCron'
import { jobTemplateLabel } from '../lib/jobTemplate'
import {
  SCHEDULE_KINDS,
  SCHEDULE_TIMEZONE,
  filterManagedSchedules,
  isManagedScheduleTemplate,
  resolveCopyMissionTarget,
  resolvePlacementScanTarget,
  scheduleDisplayTitle,
  type ScheduleKind,
} from '../lib/scheduleCatalog'
import type { CopyMissionData } from '../types/copyMission'
import type { JobScheduleData, Pagination, PersonaData } from '../types/api'
import type { BrandData } from '../types/brand'
import type { PlacementTopicData } from '../types/placementTopic'

type CopyMissionOption = CopyMissionData & { persona_id: string }

export function JobSchedulesPage() {
  const [schedules, setSchedules] = useState<JobScheduleData[]>([])
  const [otherSchedules, setOtherSchedules] = useState<JobScheduleData[]>([])
  const [topics, setTopics] = useState<PlacementTopicData[]>([])
  const [brands, setBrands] = useState<BrandData[]>([])
  const [missions, setMissions] = useState<CopyMissionOption[]>([])
  const [pagination, setPagination] = useState<Pagination | null>(null)
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)
  const [deletingId, setDeletingId] = useState('')
  const [error, setError] = useState('')

  const [kind, setKind] = useState<ScheduleKind>('placement_topic_scan')
  const [topicId, setTopicId] = useState('')
  const [missionKey, setMissionKey] = useState('')
  const [frequency, setFrequency] = useState<ScheduleFrequency>(defaultScheduleFrequency())
  const [enabled, setEnabled] = useState(false)

  const cron = useMemo(() => buildCronFromFrequency(frequency), [frequency])

  const loadCatalog = useCallback(async () => {
    const [topicsRes, personasRes, brandsRes] = await Promise.all([
      api.get<{ list: PlacementTopicData[] }>('/api/v1/placement/topics/', { auth: true }),
      api.get<{ list: PersonaData[] }>('/api/v1/personas', { auth: true }),
      api.get<{ list: BrandData[] }>('/api/v1/brands', { auth: true }),
    ])
    const topicList = topicsRes.list ?? []
    const personaList = personasRes.list ?? []
    const missionGroups = await Promise.all(
      personaList.map(async (persona) => {
        try {
          const data = await api.get<{ list: CopyMissionData[] }>(
            `/api/v1/personas/${encodeURIComponent(persona.id)}/copy-missions`,
            { auth: true },
          )
          return (data.list ?? []).map((mission) => ({ ...mission, persona_id: persona.id }))
        } catch {
          return [] as CopyMissionOption[]
        }
      }),
    )
    const flatMissions = missionGroups.flat()
    setTopics(topicList)
    setBrands(brandsRes.list ?? [])
    setMissions(flatMissions)
    setTopicId((prev) => prev || topicList[0]?.id || '')
    setMissionKey((prev) => {
      if (prev) return prev
      const first = flatMissions[0]
      return first ? `${first.persona_id}:${first.id}` : ''
    })
  }, [])

  const loadSchedules = useCallback(async () => {
    setError('')
    setLoading(true)
    try {
      const data = await api.get<{ list: JobScheduleData[]; pagination: Pagination }>(
        '/api/v1/job/schedules',
        { auth: true, query: { page: 1, pageSize: 50 } },
      )
      const all = data.list ?? []
      setSchedules(filterManagedSchedules(all))
      setOtherSchedules(all.filter((item) => !isManagedScheduleTemplate(item.template_type)))
      setPagination(data.pagination ?? null)
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '載入排程失敗')
      setSchedules([])
      setOtherSchedules([])
      setPagination(null)
    } finally {
      setLoading(false)
    }
  }, [])

  useEffect(() => {
    Promise.all([loadCatalog(), loadSchedules()]).catch(() => undefined)
  }, [loadCatalog, loadSchedules])

  const selectedKind = useMemo(
    () => SCHEDULE_KINDS.find((item) => item.kind === kind) ?? SCHEDULE_KINDS[0],
    [kind],
  )

  const selectedMission = useMemo(() => {
    const [personaId, missionId] = missionKey.split(':')
    if (!personaId || !missionId) return null
    return missions.find((item) => item.persona_id === personaId && item.id === missionId) ?? null
  }, [missionKey, missions])

  const createSchedule = async () => {
    setSaving(true)
    setError('')
    try {
      if (kind === 'placement_topic_scan') {
        if (!topicId) throw new ApiError(0, '請選擇找 TA 主題')
        await api.put(
          `/api/v1/placement/topics/${encodeURIComponent(topicId)}/scan-schedule`,
          { cron, timezone: SCHEDULE_TIMEZONE, enabled },
          { auth: true },
        )
      } else {
        if (!selectedMission) throw new ApiError(0, '請選擇拷貝任務')
        await api.put(
          `/api/v1/personas/${encodeURIComponent(selectedMission.persona_id)}/copy-missions/${encodeURIComponent(selectedMission.id)}/scan-schedule`,
          { cron, timezone: SCHEDULE_TIMEZONE, enabled },
          { auth: true },
        )
      }
      await loadSchedules()
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '儲存排程失敗')
    } finally {
      setSaving(false)
    }
  }

  const updateCron = async (schedule: JobScheduleData, nextCron: string) => {
    setError('')
    try {
      await api.put(
        `/api/v1/job/schedules/${encodeURIComponent(schedule.id)}`,
        { cron: nextCron, timezone: schedule.timezone || SCHEDULE_TIMEZONE },
        { auth: true },
      )
      await loadSchedules()
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '更新頻率失敗')
    }
  }

  const toggle = async (schedule: JobScheduleData) => {
    setError('')
    const path = schedule.enabled ? 'disable' : 'enable'
    try {
      await api.post(`/api/v1/job/schedules/${encodeURIComponent(schedule.id)}/${path}`, {}, { auth: true })
      await loadSchedules()
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '更新狀態失敗')
    }
  }

  const removeSchedule = async (schedule: JobScheduleData) => {
    const target =
      schedule.template_type === 'placement-scan'
        ? resolvePlacementScanTarget(schedule, topics, brands).label
        : resolveCopyMissionTarget(schedule, missions).label
    if (!window.confirm(`確定刪除「${target}」的排程？刪除後需重新設定，無法復原。`)) return

    setDeletingId(schedule.id)
    setError('')
    try {
      await api.delete(`/api/v1/job/schedules/${encodeURIComponent(schedule.id)}`, { auth: true })
      await loadSchedules()
    } catch (e) {
      setError(e instanceof ApiError ? e.message : '刪除排程失敗')
    } finally {
      setDeletingId('')
    }
  }

  return (
    <div>
      <PageTitle title="定時排程" subtitle="定期海巡掃貼文，發文仍須手動" />

      <div className="mb-6 space-y-3">
        <Notice
          tone="warning"
          title="排程不會自動發文"
          message="定期任務只會依頻率重跑海巡、把新貼文收進候選列表，不會在 Threads 自動 po 文或回留言。掃到合適對象後，請到找 TA 留言或拷貝任務頁手動產草稿並發佈。"
        />
        <Notice
          tone="info"
          title="目前支援兩種排程"
          message="找 TA 雙軌海巡與拷貝忍者爆款海巡。執行目標與 payload 由系統依主題／任務自動帶入，這裡只需選對象與頻率。"
        />
      </div>

      <Card className="mb-8 space-y-4">
        <div>
          <h2 className="text-base font-bold text-ink">新增或更新排程</h2>
          <p className="mt-1 text-sm leading-relaxed text-ink-secondary">
            同一主題或拷貝任務重複儲存會更新既有排程，不會建立第二筆。
          </p>
        </div>

        <Field label="排程類型">
          <Select value={kind} onChange={(e) => setKind(e.target.value as ScheduleKind)}>
            {SCHEDULE_KINDS.map((item) => (
              <option key={item.kind} value={item.kind}>
                {item.label}
              </option>
            ))}
          </Select>
        </Field>

        <p className="-mt-2 text-sm text-ink-secondary">{selectedKind.description}</p>

        {kind === 'placement_topic_scan' ? (
          <Field label="找 TA 主題" hint={selectedKind.configureHint}>
            <Select value={topicId} onChange={(e) => setTopicId(e.target.value)}>
              {topics.length === 0 ? <option value="">尚無主題，請先到找 TA 建立</option> : null}
              {topics.map((topic) => {
                const name = topic.topic_name?.trim() || topic.seed_query?.trim() || topic.id
                return (
                  <option key={topic.id} value={topic.id}>
                    {name}
                  </option>
                )
              })}
            </Select>
          </Field>
        ) : (
          <Field label="拷貝任務" hint={selectedKind.configureHint}>
            <Select value={missionKey} onChange={(e) => setMissionKey(e.target.value)}>
              {missions.length === 0 ? (
                <option value="">尚無拷貝任務，請先到拷貝忍者建立</option>
              ) : null}
              {missions.map((mission) => {
                const name = mission.label?.trim() || mission.seed_query?.trim() || mission.id
                return (
                  <option key={`${mission.persona_id}:${mission.id}`} value={`${mission.persona_id}:${mission.id}`}>
                    {name}
                  </option>
                )
              })}
            </Select>
          </Field>
        )}

        <ScheduleFrequencyPicker value={frequency} onChange={setFrequency} />
        <p className="text-sm text-muted">預覽：{describeCron(cron)}（台北時間）</p>

        <label className="flex items-center gap-2 text-sm text-ink">
          <input
            type="checkbox"
            checked={enabled}
            onChange={(e) => setEnabled(e.target.checked)}
            className="h-4 w-4 rounded border-line"
          />
          建立後立即啟用
        </label>

        <div className="flex flex-wrap gap-2">
          <Button onClick={() => void createSchedule()} disabled={saving || (kind === 'placement_topic_scan' ? !topicId : !selectedMission)}>
            {saving ? '儲存中…' : '儲存排程'}
          </Button>
          <Button variant="ghost" onClick={() => void loadSchedules()} disabled={loading}>
            重新載入列表
          </Button>
        </div>

        <ErrorText message={error} />
      </Card>

      <div className="mb-3 flex flex-wrap items-center justify-between gap-3">
        <p className="text-sm text-ink-secondary">
          {pagination ? `共 ${schedules.length} 筆可管理排程` : loading ? '載入中…' : '—'}
        </p>
      </div>

      <Card className="overflow-hidden p-0">
        {loading && schedules.length === 0 ? (
          <TableEmpty>載入排程中…</TableEmpty>
        ) : schedules.length === 0 ? (
          <TableEmpty>
            尚無海巡排程。從上方選類型與對象後儲存；若曾在「研究地圖」頁設定品牌排程，也會出現在這裡。
          </TableEmpty>
        ) : (
          <ul className="divide-y divide-line">
            {schedules.map((schedule) => {
              const target =
                schedule.template_type === 'placement-scan'
                  ? resolvePlacementScanTarget(schedule, topics, brands)
                  : resolveCopyMissionTarget(schedule, missions)
              const nextRun = formatUnixNano(schedule.next_run_at)
              const rowFrequency = frequencyFromCron(schedule.cron)

              return (
                <li key={schedule.id} className="ac-schedule-row">
                  <div className="ac-schedule-row__main">
                    <div className="ac-schedule-row__info">
                      <div className="flex flex-wrap items-center gap-2">
                        <p className="text-sm font-bold text-ink">
                          {scheduleDisplayTitle(schedule.template_type)}
                        </p>
                        <StatusBadge
                          className={schedule.enabled ? 'ac-status-badge--success' : 'ac-status-badge--muted'}
                        >
                          {schedule.enabled ? '啟用' : '停用'}
                        </StatusBadge>
                      </div>
                      <p className="text-xs text-ink-secondary">
                        {'source' in target ? (
                          <span className="text-muted">{target.source} · </span>
                        ) : null}
                        <Link to={target.href} className="font-semibold text-brand hover:underline">
                          {target.label}
                        </Link>
                        {nextRun ? <span className="ml-2 text-muted">下次 {nextRun}</span> : null}
                      </p>
                    </div>

                    <div className="ac-schedule-row__controls">
                      <ScheduleFrequencyPicker
                        compact
                        value={rowFrequency}
                        onChange={(next) => {
                          const nextCron = buildCronFromFrequency(next)
                          if (nextCron !== schedule.cron) void updateCron(schedule, nextCron)
                        }}
                      />
                    </div>

                    <div className="ac-schedule-row__actions">
                      <Button
                        variant={schedule.enabled ? 'ghost' : 'soft'}
                        className="min-h-8 px-3 py-1 text-sm"
                        onClick={() => void toggle(schedule)}
                      >
                        {schedule.enabled ? '停用' : '啟用'}
                      </Button>
                      <Button
                        variant="danger"
                        className="min-h-8 px-3 py-1 text-sm"
                        disabled={deletingId === schedule.id}
                        onClick={() => void removeSchedule(schedule)}
                      >
                        {deletingId === schedule.id ? '刪除中…' : '刪除'}
                      </Button>
                    </div>
                  </div>
                </li>
              )
            })}
          </ul>
        )}
      </Card>

      {otherSchedules.length > 0 ? (
        <Card className="mt-6 space-y-4 p-5">
          <Notice
            tone="warning"
            title="另有其他類型排程"
            message="這些排程不會出現在上方海巡列表，但會被總覽舊版統計計入。若不需要可刪除。"
          />
          <ul className="divide-y divide-line rounded-[var(--radius-lg)] border-2 border-line">
            {otherSchedules.map((schedule) => (
              <li key={schedule.id} className="flex flex-wrap items-center justify-between gap-3 px-4 py-3">
                <div className="min-w-0">
                  <p className="text-sm font-bold text-ink">{jobTemplateLabel(schedule.template_type)}</p>
                  <p className="text-xs text-muted">
                    {schedule.scope} / {schedule.scope_id.slice(0, 12)}… · {schedule.enabled ? '啟用' : '停用'}
                  </p>
                </div>
                <Button
                  variant="danger"
                  className="min-h-8 px-3 py-1 text-sm"
                  disabled={deletingId === schedule.id}
                  onClick={() => void removeSchedule(schedule)}
                >
                  {deletingId === schedule.id ? '刪除中…' : '刪除'}
                </Button>
              </li>
            ))}
          </ul>
        </Card>
      ) : null}
    </div>
  )
}