import React, { useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { PlusIcon, TrashIcon } from '@heroicons/react/24/outline';
import PageHeader from '../components/ui/PageHeader';
import ConfirmDialog from '../components/ui/ConfirmDialog';
import SearchableSelect from '../components/ui/SearchableSelect';
import PersianDateInput from '../components/ui/PersianDateInput';
import { usePermissions } from '../hooks/usePermissions';
import { useResources } from '../hooks/useResources';
import {
  useResourceAvailability, useResourceCalendar, useResourceExceptions,
} from '../hooks/useResourceCalendar';
import { formatDate } from '../lib/utils';
import type { ResourceException } from '../types';

/** ۰ = شنبه — همان قرارداد بک‌اند و ساعت کاری شعبه. */
const DAY_LABELS = ['شنبه', 'یکشنبه', 'دوشنبه', 'سه‌شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه'];

const MINUTES_IN_DAY = 1440;

/** چرا یک روز خالی است — بدون ترجمه، پاسخ خام سرور به کاربر نشان داده می‌شد. */
const REASON_LABELS: Record<string, string> = {
  national_holiday: 'تعطیل رسمی',
  tenant_holiday: 'تعطیلی این محیط',
  no_shift: 'شیفتی تعریف نشده',
  branch_closed: 'شعبه این روز بسته است',
  outside_branch_hours: 'شیفت بیرون از ساعت کاری شعبه',
  exception: 'مرخصی یا سرویس',
  resource_inactive: 'منبع غیرفعال است',
  branch_inactive: 'شعبه غیرفعال است',
};

const EXCEPTION_TYPES = [
  { value: 'leave', label: 'مرخصی' },
  { value: 'absence', label: 'غیبت' },
  { value: 'maintenance', label: 'سرویس دوره‌ای' },
  { value: 'closure', label: 'تعطیلی موردی' },
];

type Draft = { start: string; end: string; endOfDay: boolean };

function toTime(minute: number): string {
  return `${String(Math.floor(minute / 60)).padStart(2, '0')}:${String(minute % 60).padStart(2, '0')}`;
}

function toMinutes(time: string): number | null {
  const m = /^(\d{1,2}):(\d{2})$/.exec(time.trim());
  if (!m) return null;
  const minutes = Number(m[1]) * 60 + Number(m[2]);
  return minutes >= 0 && minutes <= MINUTES_IN_DAY ? minutes : null;
}

/** نیمه‌شبِ امروز به‌صورت timestamp ثانیه‌ای. */
function todayMidnight(): number {
  const d = new Date();
  d.setHours(0, 0, 0, 0);
  return Math.floor(d.getTime() / 1000);
}

/**
 * تقویم یک منبع: شیفت هفتگی، استثناها، و پیش‌نمایش ساعت آزاد.
 *
 * پیش‌نمایش عمداً «ساعت آزاد» نامیده نشده بلکه «خام» است: نوبت‌های ثبت‌شده در آن
 * کسر نشده‌اند و اشتباه گرفتنش با «وقت قابل رزرو» به بیش‌رزروی می‌انجامد.
 */
export default function ResourceCalendarPage() {
  const { resourceUuid } = useParams<{ resourceUuid: string }>();
  const { calendar, loading, save } = useResourceCalendar(resourceUuid);
  const { exceptions, create, remove } = useResourceExceptions(resourceUuid);
  const { resources } = useResources();
  const { can } = usePermissions();
  const canUpdate = can('appointment_settings', 'update');

  const resource = resources.find((r) => r.uuid === resourceUuid);

  const [draft, setDraft] = useState<Record<number, Draft[]>>({});
  const [error, setError] = useState<string | null>(null);
  const [toDelete, setToDelete] = useState<ResourceException | null>(null);

  const previewFrom = todayMidnight();
  const previewTo = previewFrom + 13 * 86400;
  const { availability } = useResourceAvailability(resourceUuid, previewFrom, previewTo);

  useEffect(() => {
    if (!calendar) return;
    const next: Record<number, Draft[]> = {};
    DAY_LABELS.forEach((_, day) => {
      next[day] = (calendar.days[String(day)] ?? []).map((r) => ({
        start: toTime(r.start_minute),
        end: r.end_minute === MINUTES_IN_DAY ? '23:59' : toTime(r.end_minute),
        endOfDay: r.end_minute === MINUTES_IN_DAY,
      }));
    });
    setDraft(next);
  }, [calendar]);

  const totalShifts = useMemo(
    () => Object.values(draft).reduce((sum, rows) => sum + rows.length, 0),
    [draft],
  );

  const editRange = (day: number, index: number, patch: Partial<Draft>) =>
    setDraft((d) => ({ ...d, [day]: (d[day] ?? []).map((r, i) => (i === index ? { ...r, ...patch } : r)) }));

  const submit = () => {
    const days: Record<string, { start_minute: number; end_minute: number }[]> = {};

    for (const [dayKey, rows] of Object.entries(draft)) {
      const parsed: { start_minute: number; end_minute: number }[] = [];

      for (const row of rows) {
        const start = toMinutes(row.start);
        const end = row.endOfDay ? MINUTES_IN_DAY : toMinutes(row.end);

        if (start === null || end === null) {
          setError(`ساعت روز ${DAY_LABELS[Number(dayKey)]} را به شکل ۰۹:۰۰ وارد کنید`);
          return;
        }
        if (end <= start) {
          setError(`در روز ${DAY_LABELS[Number(dayKey)]} پایان شیفت باید بعد از شروع آن باشد`);
          return;
        }
        parsed.push({ start_minute: start, end_minute: end });
      }

      days[dayKey] = parsed;
    }

    setError(null);
    save.mutate(days);
  };

  return (
    <div className="fade-in">
      <PageHeader
        title={`تقویم ${resource?.name ?? 'منبع'}`}
        description="شیفت هفتگی منبع. ساعت واقعی از تقاطع این شیفت‌ها با ساعت کاری شعبه به‌دست می‌آید و تعطیلات و مرخصی از آن کسر می‌شود."
        backTo="/admin/resources"
        breadcrumbs={[{ label: 'منابع', to: '/admin/resources' }, { label: 'تقویم' }]}
        action={
          canUpdate ? (
            <button type="button" className="btn primary" disabled={save.isPending} onClick={submit}>
              {save.isPending ? 'در حال ذخیره...' : 'ذخیرهٔ شیفت‌ها'}
            </button>
          ) : undefined
        }
      />

      {error && (
        <div
          className="card"
          style={{ padding: '12px 16px', marginBottom: 16, color: 'var(--danger)', background: 'var(--danger-bg)', fontSize: 13 }}
        >
          {error}
        </div>
      )}

      <div style={{ display: 'grid', gap: 16, gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))' }}>
        <section style={{ display: 'grid', gap: 12 }}>
          <h2 className="section-title" style={{ margin: 0 }}>
            شیفت هفتگی {totalShifts > 0 && <span style={{ fontSize: 12, color: 'var(--text-3)' }}>({totalShifts} شیفت)</span>}
          </h2>

          {loading ? (
            <div style={{ padding: 16, color: 'var(--text-3)', fontSize: 13 }}>در حال بارگذاری...</div>
          ) : (
            DAY_LABELS.map((label, day) => {
              const rows = draft[day] ?? [];
              return (
                <div key={day} className="card" style={{ padding: 14 }}>
                  <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10, marginBottom: rows.length ? 10 : 0 }}>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                      <span style={{ fontWeight: 700, fontSize: 14 }}>{label}</span>
                      {rows.length === 0 && <span style={{ fontSize: 12, color: 'var(--text-3)' }}>بدون شیفت</span>}
                    </div>
                    {canUpdate && (
                      <button
                        type="button"
                        className="btn secondary sm"
                        onClick={() => setDraft((d) => ({ ...d, [day]: [...(d[day] ?? []), { start: '09:00', end: '17:00', endOfDay: false }] }))}
                      >
                        <PlusIcon style={{ width: 15 }} /> شیفت
                      </button>
                    )}
                  </div>

                  <div style={{ display: 'grid', gap: 8 }}>
                    {rows.map((row, index) => (
                      <div key={index} style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                        <input
                          type="time"
                          className="field"
                          value={row.start}
                          disabled={!canUpdate}
                          onChange={(e) => editRange(day, index, { start: e.target.value })}
                          style={{ width: 116 }}
                        />
                        <span style={{ fontSize: 12, color: 'var(--text-3)' }}>تا</span>
                        {row.endOfDay ? (
                          <span className="field" style={{ width: 116, color: 'var(--text-2)' }}>۲۴:۰۰</span>
                        ) : (
                          <input
                            type="time"
                            className="field"
                            value={row.end}
                            disabled={!canUpdate}
                            onChange={(e) => editRange(day, index, { end: e.target.value })}
                            style={{ width: 116 }}
                          />
                        )}
                        <label style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 12, color: 'var(--text-3)' }}>
                          <input
                            type="checkbox"
                            checked={row.endOfDay}
                            disabled={!canUpdate}
                            onChange={(e) => editRange(day, index, { endOfDay: e.target.checked })}
                          />
                          تا پایان روز
                        </label>
                        {canUpdate && (
                          <button
                            type="button"
                            className="btn secondary sm"
                            onClick={() => setDraft((d) => ({ ...d, [day]: (d[day] ?? []).filter((_, i) => i !== index) }))}
                            aria-label="حذف شیفت"
                          >
                            <TrashIcon style={{ width: 15 }} />
                          </button>
                        )}
                      </div>
                    ))}
                  </div>
                </div>
              );
            })
          )}
        </section>

        <section style={{ display: 'grid', gap: 12, alignContent: 'start' }}>
          <ExceptionsCard
            exceptions={exceptions}
            canUpdate={canUpdate}
            saving={create.isPending}
            onCreate={(payload) => create.mutate(payload)}
            onDelete={setToDelete}
          />

          <div className="card" style={{ padding: 14 }}>
            <h2 className="section-title" style={{ margin: '0 0 4px' }}>پیش‌نمایش دو هفته</h2>
            <p style={{ fontSize: 12, color: 'var(--text-3)', margin: '0 0 10px' }}>
              ساعت <strong>خام</strong> — نوبت‌های ثبت‌شده هنوز از آن کسر نشده‌اند.
            </p>

            <div style={{ display: 'grid', gap: 6 }}>
              {(availability?.days ?? []).map((day) => (
                <div
                  key={day.date}
                  style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, fontSize: 13 }}
                >
                  <span style={{ color: 'var(--text-2)' }}>
                    {DAY_LABELS[day.day_of_week]} · {formatDate(day.date * 1000)}
                  </span>
                  {day.intervals.length === 0 ? (
                    <span style={{ fontSize: 12, color: 'var(--text-3)' }}>
                      {day.reasons.map((r) => REASON_LABELS[r] ?? r).join('، ') || '—'}
                    </span>
                  ) : (
                    <span style={{ fontWeight: 600 }}>{day.total_minutes} دقیقه</span>
                  )}
                </div>
              ))}
            </div>
          </div>
        </section>
      </div>

      <ConfirmDialog
        open={!!toDelete}
        title="حذف استثنا"
        message={`آیا از حذف «${toDelete?.type_label}» مطمئن هستید؟`}
        confirmLabel="حذف"
        loading={remove.isPending}
        onConfirm={() => toDelete && remove.mutate(toDelete.uuid, { onSuccess: () => setToDelete(null) })}
        onCancel={() => setToDelete(null)}
      />
    </div>
  );
}

function ExceptionsCard({
  exceptions, canUpdate, saving, onCreate, onDelete,
}: {
  exceptions: ResourceException[];
  canUpdate: boolean;
  saving: boolean;
  onCreate: (payload: { type: string; starts_at: number; ends_at: number; reason?: string | null }) => void;
  onDelete: (e: ResourceException) => void;
}) {
  const [type, setType] = useState<string>('leave');
  const [startDate, setStartDate] = useState('');
  const [endDate, setEndDate] = useState('');
  const [reason, setReason] = useState('');

  const toTimestamp = (value: string): number | null => {
    if (value === '') return null;
    const ms = new Date(`${value}T00:00:00`).getTime();
    return Number.isNaN(ms) ? null : Math.floor(ms / 1000);
  };

  const start = toTimestamp(startDate);
  const end = toTimestamp(endDate);
  // پایان روزِ انتخاب‌شده، نه آغازش: مرخصیِ «تا سه‌شنبه» شامل خودِ سه‌شنبه است.
  const endExclusive = end === null ? null : end + 86400;
  const invalid = start === null || endExclusive === null || endExclusive <= start;

  return (
    <div className="card" style={{ padding: 14 }}>
      <h2 className="section-title" style={{ margin: '0 0 10px' }}>مرخصی و سرویس</h2>

      {exceptions.length === 0 ? (
        <p style={{ fontSize: 13, color: 'var(--text-3)', margin: '0 0 10px' }}>استثنایی ثبت نشده است.</p>
      ) : (
        <div style={{ display: 'grid', gap: 8, marginBottom: 12 }}>
          {exceptions.map((e) => (
            <div key={e.uuid} style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13 }}>
              <span className="badge amber" style={{ fontSize: 11 }}>{e.type_label}</span>
              <span style={{ flex: 1, color: 'var(--text-2)' }}>
                {formatDate(e.starts_at * 1000)} تا {formatDate(e.ends_at * 1000)}
                {e.reason ? ` · ${e.reason}` : ''}
              </span>
              {canUpdate && (
                <button type="button" className="btn secondary sm" onClick={() => onDelete(e)} aria-label="حذف استثنا">
                  ✕
                </button>
              )}
            </div>
          ))}
        </div>
      )}

      {canUpdate && (
        <div style={{ display: 'grid', gap: 8 }}>
          <SearchableSelect
            options={EXCEPTION_TYPES}
            value={type}
            onChange={(v) => setType(v ? String(v) : 'leave')}
            placeholder="نوع استثنا"
            height={36}
          />
          {/* تقویم شمسی، نه `input type=date` میلادی: اپراتور تاریخ را شمسی می‌گوید و
              ترجمهٔ ذهنی همان‌جایی است که استثنا یک روز جابه‌جا ثبت می‌شود. */}
          <div style={{ display: 'flex', gap: 8 }}>
            <div style={{ flex: 1 }}>
              <PersianDateInput value={startDate} onChange={setStartDate} placeholder="از تاریخ" />
            </div>
            <div style={{ flex: 1 }}>
              <PersianDateInput value={endDate} onChange={setEndDate} placeholder="تا تاریخ" />
            </div>
          </div>
          <input className="field" value={reason} onChange={(e) => setReason(e.target.value)} placeholder="توضیح (اختیاری)" />
          <button
            type="button"
            className="btn secondary"
            disabled={saving || invalid}
            onClick={() => {
              onCreate({
                type,
                starts_at: start!,
                ends_at: endExclusive!,
                reason: reason.trim() === '' ? null : reason.trim(),
              });
              setStartDate('');
              setEndDate('');
              setReason('');
            }}
          >
            {saving ? 'در حال ثبت...' : 'ثبت استثنا'}
          </button>
        </div>
      )}
    </div>
  );
}
