import React, { useEffect, useMemo, useState } from 'react';
import {
  ExclamationTriangleIcon, PlusIcon, Square2StackIcon, TrashIcon,
} from '@heroicons/react/24/outline';
import { useResourceCalendar } from '../../hooks/useResourceCalendar';
import { formatNumber } from '../../lib/utils';

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

const MINUTES_IN_DAY = 1440;

type Draft = { start: string; end: string; endOfDay: boolean };
type Days = Record<number, Draft[]>;

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;
}

/**
 * شیفت هفتگی یک منبع — روزهای کاری و ساعت هر روز.
 *
 * با حذف دامنهٔ شعبه، این شیفت تنها مرجع ساعت کاری منبع است؛ فقط تعطیلات رسمی و
 * استثناهای خودِ منبع از آن کسر می‌شوند.
 *
 * چیدمان عمداً تک‌ستونه است: هفته یک توالی است و گرید دوستونه ترتیبش را زیگزاگ
 * می‌کرد. ذخیره در `save-bar` چسبان می‌نشیند تا هم پایینِ فیلدها باشد و هم
 * وجودش خودش نشانهٔ «ذخیره‌نشده» باشد.
 */
export default function ResourceWorkingHoursPanel({ resourceUuid, canUpdate }: {
  resourceUuid?: string;
  canUpdate: boolean;
}) {
  const { calendar, loading, save } = useResourceCalendar(resourceUuid);

  const [draft, setDraft] = useState<Days>({});
  // نسخهٔ سرور به‌صورت رشته نگه داشته می‌شود تا مقایسهٔ dirty یک `===` ساده باشد.
  const [baseline, setBaseline] = useState<string | null>(null);
  const [error, setError] = useState<{ day: number; message: string } | null>(null);

  useEffect(() => {
    if (!calendar) return;
    const next: Days = {};
    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);
    setBaseline(JSON.stringify(next));
    setError(null);
  }, [calendar]);

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

  // پیش از اولین پاسخ سرور baseline نداریم، پس هیچ‌چیز dirty نیست.
  const dirty = baseline !== null && JSON.stringify(draft) !== baseline;

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

  const addRange = (day: number) =>
    setDraft((d) => ({ ...d, [day]: [...(d[day] ?? []), { start: '09:00', end: '17:00', endOfDay: false }] }));

  const removeRange = (day: number, index: number) =>
    setDraft((d) => ({ ...d, [day]: (d[day] ?? []).filter((_, i) => i !== index) }));

  /** پرتکرارترین حالت، یک ساعتِ یکسان برای همهٔ روزهای کاری است؛ بدون این، تعریف
   *  یک هفتهٔ ساده ۱۵ تعامل می‌خواست. */
  const copyToAllDays = (day: number) =>
    setDraft((d) => {
      const source = (d[day] ?? []).map((r) => ({ ...r }));
      const next: Days = {};
      DAY_LABELS.forEach((_, i) => { next[i] = source.map((r) => ({ ...r })); });
      return next;
    });

  const reset = () => {
    if (baseline === null) return;
    setDraft(JSON.parse(baseline) as Days);
    setError(null);
  };

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

    for (const [dayKey, rows] of Object.entries(draft)) {
      const day = Number(dayKey);
      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, message: `ساعت روز ${DAY_LABELS[day]} را به شکل ۰۹:۰۰ وارد کنید` });
          return;
        }
        if (end <= start) {
          setError({ day, message: `در روز ${DAY_LABELS[day]} پایان شیفت باید بعد از شروع آن باشد` });
          return;
        }
        parsed.push({ start_minute: start, end_minute: end });
      }

      days[dayKey] = parsed;
    }

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

  return (
    <div className="card card-pad">
      <div className="card-title-row" style={{ marginBottom: 6 }}>
        <h2 style={{ fontSize: 16, fontWeight: 700, color: 'var(--text)' }}>شیفت هفتگی</h2>
        {totalShifts > 0 && <span className="badge gray">{formatNumber(totalShifts)} شیفت</span>}
      </div>

      <p className="field-hint" style={{ marginTop: 0, marginBottom: 14 }}>
        روزهای کاری و ساعت هر روز. تعطیلات رسمی و مرخصی از همین ساعت کسر می‌شوند.
      </p>

      {error && (
        <div
          role="alert"
          style={{
            display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12,
            padding: '10px 14px', borderRadius: 'var(--r-sm)',
            background: 'var(--danger-bg)', color: 'var(--danger)', fontSize: 13, fontWeight: 600,
          }}
        >
          <ExclamationTriangleIcon style={{ width: 16, flexShrink: 0 }} />
          {error.message}
        </div>
      )}

      {loading ? (
        <div style={{ display: 'grid', gap: 10 }}>
          {DAY_LABELS.map((_, i) => (
            <div key={i} className="skeleton" style={{ height: 56, borderRadius: 'var(--r-sm)' }} />
          ))}
        </div>
      ) : (
        <div style={{ display: 'grid', gap: 10 }}>
          {DAY_LABELS.map((label, day) => {
            const rows = draft[day] ?? [];
            const cls = ['wh-day', rows.length ? 'has-shift' : '', error?.day === day ? 'err' : '']
              .filter(Boolean).join(' ');

            return (
              <div key={day} className={cls}>
                <div className="wh-day-name">{label}</div>

                {rows.length === 0 ? (
                  <div className="wh-day-off">بدون شیفت — این روز بسته است</div>
                ) : (
                  <div className="wh-rows">
                    {rows.map((row, index) => (
                      <div key={index} className="wh-shift">
                        <label className="field wh-time">
                          <span className="lbl">از</span>
                          <input
                            type="time"
                            value={row.start}
                            disabled={!canUpdate}
                            onChange={(e) => editRange(day, index, { start: e.target.value })}
                            aria-label={`ساعت شروع شیفت ${formatNumber(index + 1)} روز ${label}`}
                          />
                        </label>

                        <label className="field wh-time">
                          <span className="lbl">تا</span>
                          {row.endOfDay ? (
                            <span style={{ color: 'var(--text-2)', fontSize: 13.5 }}>۲۴:۰۰</span>
                          ) : (
                            <input
                              type="time"
                              value={row.end}
                              disabled={!canUpdate}
                              onChange={(e) => editRange(day, index, { end: e.target.value })}
                              aria-label={`ساعت پایان شیفت ${formatNumber(index + 1)} روز ${label}`}
                            />
                          )}
                        </label>

                        <label className="wh-eod">
                          <input
                            type="checkbox"
                            checked={row.endOfDay}
                            disabled={!canUpdate}
                            onChange={(e) => editRange(day, index, { endOfDay: e.target.checked })}
                          />
                          تا پایان روز
                        </label>

                        {canUpdate && (
                          <button
                            type="button"
                            className="mini-btn danger"
                            onClick={() => removeRange(day, index)}
                            aria-label={`حذف شیفت ${formatNumber(index + 1)} روز ${label}`}
                          >
                            <TrashIcon style={{ width: 16 }} />
                          </button>
                        )}
                      </div>
                    ))}
                  </div>
                )}

                {canUpdate && (
                  <div className="wh-actions">
                    {rows.length > 0 && (
                      <button
                        type="button"
                        className="mini-btn"
                        onClick={() => copyToAllDays(day)}
                        title="کپی به همهٔ روزهای هفته"
                        aria-label={`کپی شیفت‌های ${label} به همهٔ روزهای هفته`}
                      >
                        <Square2StackIcon style={{ width: 16 }} />
                      </button>
                    )}
                    <button type="button" className="btn secondary sm" onClick={() => addRange(day)}>
                      <PlusIcon style={{ width: 15 }} /> شیفت
                    </button>
                  </div>
                )}
              </div>
            );
          })}
        </div>
      )}

      {canUpdate && dirty && (
        <div className="save-bar">
          <div className="sb-msg">
            <ExclamationTriangleIcon style={{ width: 17, color: 'var(--warning)' }} />
            تغییرات شیفت ذخیره نشده است
          </div>
          <div className="sb-actions">
            <button type="button" className="btn ghost" disabled={save.isPending} onClick={reset}>
              بازگرداندن
            </button>
            <button type="button" className="btn primary" disabled={save.isPending} onClick={submit}>
              {save.isPending ? 'در حال ذخیره...' : 'ذخیرهٔ شیفت‌ها'}
            </button>
          </div>
        </div>
      )}
    </div>
  );
}
