import React, { useId, useMemo, useState } from 'react';
import { Link } from 'react-router-dom';
import { XMarkIcon } from '@heroicons/react/24/outline';
import ConfirmDialog from '../ui/ConfirmDialog';
import SearchableSelect from '../ui/SearchableSelect';
import PersianDateInput from '../ui/PersianDateInput';
import { useResourceAvailability, useResourceExceptions } from '../../hooks/useResourceCalendar';
import { formatDate, formatNumber } from '../../lib/utils';
import { DAY_LABELS } from './ResourceWorkingHoursPanel';
import NationalHolidaysCard from '../holidays/NationalHolidaysCard';
import type { ResourceAvailability, ResourceException } from '../../types';

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

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

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

/**
 * تعطیلات و استثناهای یک منبع، کنار پیش‌نمایش دو هفتهٔ ساعت آزاد.
 *
 * پیش‌نمایش عمداً «ساعت آزاد» نامیده نشده بلکه «خام» است: نوبت‌های ثبت‌شده در آن
 * کسر نشده‌اند و اشتباه گرفتنش با «وقت قابل رزرو» به بیش‌رزروی می‌انجامد.
 *
 * دو ستون، نه `auto-fit`: تعطیلات و استثنا هر دو ورودی‌اند و کنار هم می‌مانند،
 * پیش‌نمایش خروجی است و ستون خودش را می‌گیرد.
 */
export default function ResourceExceptionsPanel({ resourceUuid, canUpdate }: {
  resourceUuid?: string;
  canUpdate: boolean;
}) {
  const { exceptions, create, remove } = useResourceExceptions(resourceUuid);
  const [toDelete, setToDelete] = useState<ResourceException | null>(null);

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

  return (
    <div className="wh-two-col">
      <div style={{ display: 'grid', gap: 'var(--gap)' }}>
        <NationalHolidaysCard canUpdate={canUpdate} />
        <ExceptionsCard
          exceptions={exceptions}
          canUpdate={canUpdate}
          saving={create.isPending}
          onCreate={(payload) => create.mutate(payload)}
          onDelete={setToDelete}
        />
      </div>

      <PreviewCard availability={availability} />

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

/**
 * پیش‌نمایش دو هفته.
 *
 * ۱۴ سطرِ یکنواختِ «شیفتی تعریف نشده» فقط نویز است و با یک حالت خالیِ راه‌حل‌دار
 * جمع می‌شود. شرط عمداً تنگ است: اگر حتی یک روز به دلیل دیگری (تعطیل رسمی،
 * مرخصی) بسته باشد سطرها می‌مانند، چون آن دلیل خودش اطلاعات است — نه نویز.
 */
function PreviewCard({ availability }: { availability?: ResourceAvailability }) {
  const days = availability?.days ?? [];
  const nothingConfigured = days.length > 0
    && days.every((d) => d.intervals.length === 0
      && d.reasons.length > 0
      && d.reasons.every((r) => r === 'no_shift'));

  return (
    <div className="card card-pad" style={{ position: 'sticky', top: 'var(--gap)' }}>
      <h2 style={{ fontSize: 16, fontWeight: 700, color: 'var(--text)' }}>پیش‌نمایش دو هفته</h2>
      <p className="field-hint" style={{ marginTop: 4, marginBottom: 14 }}>
        ساعت <strong>خام</strong> — نوبت‌های ثبت‌شده هنوز از آن کسر نشده‌اند.
      </p>

      {days.length === 0 ? (
        <div className="skeleton" style={{ height: 120, borderRadius: 'var(--r-sm)' }} />
      ) : nothingConfigured ? (
        <p style={{ fontSize: 13, color: 'var(--text-3)', margin: 0, lineHeight: 1.9 }}>
          در دو هفتهٔ آینده هیچ ساعتی باز نیست. اول در «شیفت هفتگی» روزهای کاری را تعریف کنید.
        </p>
      ) : (
        <div style={{ display: 'grid', gap: 7 }}>
          {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)}
              </span>
              {day.intervals.length === 0 ? (
                <span className="badge gray" style={{ fontSize: 11 }}>
                  {day.reasons.map((r) => REASON_LABELS[r] ?? r).join('، ') || '—'}
                </span>
              ) : (
                <span style={{ fontWeight: 700 }}>{formatNumber(day.total_minutes)} دقیقه</span>
              )}
            </div>
          ))}
        </div>
      )}
    </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('');

  // id یکتا لازم است: این کارت در صفحهٔ منبع و صفحهٔ تنظیمات نوبت‌دهی هر دو رندر می‌شود.
  const uid = useId();

  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;

  const typeLabel = useMemo(
    () => EXCEPTION_TYPES.find((t) => t.value === type)?.label ?? '',
    [type],
  );

  return (
    <div className="card card-pad">
      <h2 style={{ fontSize: 16, fontWeight: 700, color: 'var(--text)', marginBottom: 12 }}>
        مرخصی و سرویس
      </h2>

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

      {canUpdate ? (
        <div style={{ display: 'grid', gap: 12 }}>
          <div className="field-block">
            <label id={`${uid}-type-label`} htmlFor={`${uid}-type`}>نوع استثنا</label>
            <SearchableSelect
              inputId={`${uid}-type`}
              ariaLabelledBy={`${uid}-type-label`}
              options={EXCEPTION_TYPES}
              value={type}
              onChange={(v) => setType(v ? String(v) : 'leave')}
              placeholder="نوع استثنا"
              height={40}
            />
          </div>

          {/* تقویم شمسی، نه `input type=date` میلادی: اپراتور تاریخ را شمسی می‌گوید و
              ترجمهٔ ذهنی همان‌جایی است که استثنا یک روز جابه‌جا ثبت می‌شود. */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <div className="field-block">
              <label>از تاریخ</label>
              <PersianDateInput
                value={startDate}
                onChange={setStartDate}
                placeholder="از تاریخ"
                ariaLabel={`تاریخ شروع ${typeLabel}`}
              />
            </div>
            <div className="field-block">
              <label>تا تاریخ</label>
              <PersianDateInput
                value={endDate}
                onChange={setEndDate}
                placeholder="تا تاریخ"
                ariaLabel={`تاریخ پایان ${typeLabel}`}
              />
            </div>
          </div>

          <div className="field-block">
            <label htmlFor={`${uid}-reason`}>توضیح <span className="opt">(اختیاری)</span></label>
            <label className="field">
              <input
                id={`${uid}-reason`}
                value={reason}
                onChange={(e) => setReason(e.target.value)}
                placeholder="مثلاً سرویس سالانهٔ دستگاه"
              />
            </label>
          </div>

          <button
            type="button"
            className="btn primary"
            disabled={saving || invalid}
            onClick={() => {
              onCreate({
                type,
                starts_at: start!,
                ends_at: endExclusive!,
                reason: reason.trim() === '' ? null : reason.trim(),
              });
              setStartDate('');
              setEndDate('');
              setReason('');
            }}
          >
            {saving ? 'در حال ثبت...' : 'ثبت استثنا'}
          </button>
        </div>
      ) : (
        <p style={{ fontSize: 12.5, color: 'var(--text-3)', margin: 0 }}>
          برای ثبت یا حذف استثنا مجوز ویرایش تنظیمات نوبت‌دهی لازم است.
        </p>
      )}
    </div>
  );
}
