import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
  View, Text, TouchableOpacity, StyleSheet, RefreshControl,
  ActivityIndicator, ScrollView, Modal, Alert,
} from 'react-native';
import { colors } from '../../theme/colors';
import { typography } from '../../theme/typography';
import { spacing } from '../../theme/spacing';
import { Card, Button } from '../../components/ui';
import { api } from '../../services/api';

interface ScheduleEntry {
  id: string; clubId: string; trainerId: string; date: string;
  startTime: string; endTime: string; isAvailable: boolean;
  trainer: { id: string; firstName: string; lastName: string };
}

const DAYS = ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
const MONTHS = [
  'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь',
  'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь',
];
const TIMES = [
  '06:00', '07:00', '08:00', '09:00', '10:00', '11:00', '12:00',
  '13:00', '14:00', '15:00', '16:00', '17:00', '18:00',
  '19:00', '20:00', '21:00', '22:00',
];

function fmt(d: Date): string {
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}
function isToday(d: Date): boolean {
  const n = new Date();
  return d.getDate() === n.getDate() && d.getMonth() === n.getMonth() && d.getFullYear() === n.getFullYear();
}
function getMonday(date: Date): Date {
  const d = new Date(date);
  d.setDate(d.getDate() - ((d.getDay() + 6) % 7));
  d.setHours(0, 0, 0, 0);
  return d;
}
function weekFrom(mon: Date) {
  return Array.from({ length: 7 }, (_, i) => {
    const d = new Date(mon); d.setDate(mon.getDate() + i);
    return { key: fmt(d), name: DAYS[i], num: d.getDate(), today: isToday(d) };
  });
}

export function WorkScheduleScreen(): React.JSX.Element {
  const st = createSt();
  const [monday, setMonday] = useState(() => getMonday(new Date()));
  const [sel, setSel] = useState(fmt(new Date()));
  const [entries, setEntries] = useState<ScheduleEntry[]>([]);
  const [loading, setLoading] = useState(false);
  const [refreshing, setRefreshing] = useState(false);
  const [modal, setModal] = useState(false);
  const [start, setStart] = useState('09:00');
  const [end, setEnd] = useState('18:00');
  const [saving, setSaving] = useState(false);

  const days = useMemo(() => weekFrom(monday), [monday]);
  const monthTitle = useMemo(() => {
    const d = new Date(sel + 'T00:00:00');
    return `${MONTHS[d.getMonth()]} ${d.getFullYear()}`;
  }, [sel]);
  const entry = useMemo(() => entries.find((e) => e.date.startsWith(sel)), [entries, sel]);

  const load = useCallback(async (ref = false) => {
    ref ? setRefreshing(true) : setLoading(true);
    try {
      const data = await api.get<ScheduleEntry[]>('/work-schedule', {
        params: { dateFrom: days[0].key, dateTo: days[6].key },
      });
      setEntries(data);
    } catch { Alert.alert('Ошибка', 'Не удалось загрузить график работы'); }
    finally { setLoading(false); setRefreshing(false); }
  }, [days]);

  useEffect(() => { load(); }, [load]);

  const shiftWeek = useCallback((dir: number) => {
    setMonday((p) => { const n = new Date(p); n.setDate(p.getDate() + dir * 7); return n; });
  }, []);

  const toggleAvail = useCallback(async () => {
    if (!entry) return;
    try {
      const u = await api.patch<ScheduleEntry>(
        `/work-schedule/${entry.id}`, { isAvailable: !entry.isAvailable },
      );
      setEntries((p) => p.map((e) => (e.id === u.id ? u : e)));
    } catch { Alert.alert('Ошибка', 'Не удалось обновить статус'); }
  }, [entry]);

  const handleSave = useCallback(async () => {
    if (start >= end) { Alert.alert('Ошибка', 'Время начала должно быть раньше окончания'); return; }
    setSaving(true);
    try {
      const c = await api.post<ScheduleEntry>('/work-schedule', {
        date: sel, startTime: start, endTime: end, isAvailable: true,
      });
      setEntries((p) => [...p, c]);
      setModal(false);
    } catch { Alert.alert('Ошибка', 'Не удалось сохранить график'); }
    finally { setSaving(false); }
  }, [sel, start, end]);

  const timePicker = (val: string, set: (v: string) => void, pfx: string) => (
    <ScrollView horizontal showsHorizontalScrollIndicator={false}>
      <View style={st.chips}>
        {TIMES.map((t) => (
          <TouchableOpacity key={`${pfx}-${t}`}
            style={[st.chip, val === t && st.chipOn]} onPress={() => set(t)}>
            <Text style={[st.chipTxt, val === t && st.chipTxtOn]}>{t}</Text>
          </TouchableOpacity>
        ))}
      </View>
    </ScrollView>
  );

  return (
    <View style={st.root}>
      <View style={st.hdr}>
        <TouchableOpacity onPress={() => shiftWeek(-1)} activeOpacity={0.6}>
          <Text style={st.arrow}>{'<'}</Text>
        </TouchableOpacity>
        <Text style={st.month}>{monthTitle}</Text>
        <TouchableOpacity onPress={() => shiftWeek(1)} activeOpacity={0.6}>
          <Text style={st.arrow}>{'>'}</Text>
        </TouchableOpacity>
      </View>
      <View style={st.week}>
        {days.map((d) => {
          const isSel = d.key === sel;
          const has = entries.some((e) => e.date.startsWith(d.key));
          return (
            <TouchableOpacity key={d.key} activeOpacity={0.7}
              style={[st.dayItem, isSel && st.daySel, d.today && !isSel && st.dayTdy]}
              onPress={() => setSel(d.key)}>
              <Text style={[st.dayNm, isSel && st.daySelTxt]}>{d.name}</Text>
              <Text style={[st.dayNo, isSel && st.daySelTxt, d.today && !isSel && st.dayTdyNo]}>
                {d.num}
              </Text>
              {has && !isSel && <View style={st.dot} />}
            </TouchableOpacity>
          );
        })}
      </View>
      <ScrollView style={st.body} contentContainerStyle={st.bodyIn}
        refreshControl={<RefreshControl refreshing={refreshing} onRefresh={() => load(true)}
          tintColor={colors.primary} colors={[colors.primary]} />}>
        {loading && !refreshing ? (
          <View style={st.ctr}><ActivityIndicator size="large" color={colors.primary} /></View>
        ) : entry ? (
          <Card style={st.card}>
            <View style={st.cardHd}>
              <Text style={st.cardTtl}>Рабочий день</Text>
              <TouchableOpacity activeOpacity={0.7} onPress={toggleAvail}
                style={[st.badge, entry.isAvailable ? st.bgOn : st.bgOff]}>
                <Text style={[st.bdgTxt, !entry.isAvailable && st.bdgTxtOff]}>
                  {entry.isAvailable ? 'Доступен' : 'Недоступен'}
                </Text>
              </TouchableOpacity>
            </View>
            <View style={st.tRow}>
              <View style={st.tBlk}>
                <Text style={st.tLbl}>Начало</Text>
                <Text style={st.tVal}>{entry.startTime}</Text>
              </View>
              <Text style={st.tDash}>-</Text>
              <View style={st.tBlk}>
                <Text style={st.tLbl}>Окончание</Text>
                <Text style={st.tVal}>{entry.endTime}</Text>
              </View>
            </View>
          </Card>
        ) : (
          <View style={st.empty}>
            <Text style={st.emTtl}>Нет расписания</Text>
            <Text style={st.emSub}>На выбранную дату график работы не задан</Text>
            <Button title="Добавить" onPress={() => setModal(true)} style={st.addBtn} />
          </View>
        )}
      </ScrollView>
      <Modal visible={modal} animationType="slide" transparent>
        <View style={st.overlay}>
          <View style={st.sheet}>
            <Text style={st.shTtl}>Добавить график</Text>
            <Text style={st.shDate}>{sel}</Text>
            <Text style={st.lbl}>Начало смены</Text>
            {timePicker(start, setStart, 's')}
            <Text style={st.lbl}>Окончание смены</Text>
            {timePicker(end, setEnd, 'e')}
            <View style={st.acts}>
              <Button title="Отмена" variant="outline"
                onPress={() => setModal(false)} style={st.actBtn} />
              <Button title="Сохранить" onPress={handleSave}
                loading={saving} style={st.actBtn} />
            </View>
          </View>
        </View>
      </Modal>
    </View>
  );
}

const createSt = () => StyleSheet.create({
  root: { flex: 1, backgroundColor: colors.background },
  hdr: {
    flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between',
    backgroundColor: colors.white, paddingHorizontal: spacing.lg, paddingVertical: spacing.md,
  },
  arrow: { ...typography.h3, color: colors.primary, paddingHorizontal: spacing.sm },
  month: { ...typography.subtitle, color: colors.text },
  week: {
    flexDirection: 'row', backgroundColor: colors.white, paddingVertical: spacing.sm,
    paddingHorizontal: spacing.xs, borderBottomWidth: 1, borderBottomColor: colors.border,
  },
  dayItem: { flex: 1, alignItems: 'center', paddingVertical: spacing.sm, borderRadius: 12 },
  daySel: { backgroundColor: colors.primary },
  dayTdy: { backgroundColor: colors.background },
  dayNm: { ...typography.caption, color: colors.textSecondary, marginBottom: spacing.xs },
  dayNo: { ...typography.body, fontWeight: '700', color: colors.text },
  daySelTxt: { color: colors.white },
  dayTdyNo: { color: colors.primary },
  dot: { width: 6, height: 6, borderRadius: 3, backgroundColor: colors.success, marginTop: spacing.xs },
  body: { flex: 1 },
  bodyIn: { padding: spacing.lg },
  ctr: { paddingTop: spacing.xxxl * 2, alignItems: 'center' },
  card: { marginBottom: spacing.lg },
  cardHd: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: spacing.lg },
  cardTtl: { ...typography.subtitle, color: colors.text },
  badge: { paddingHorizontal: spacing.md, paddingVertical: spacing.xs, borderRadius: 16 },
  bgOn: { backgroundColor: colors.success + '20' },
  bgOff: { backgroundColor: colors.textMuted + '20' },
  bdgTxt: { ...typography.caption, fontWeight: '600', color: colors.success },
  bdgTxtOff: { color: colors.textMuted },
  tRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center' },
  tBlk: { alignItems: 'center', flex: 1 },
  tLbl: { ...typography.caption, color: colors.textSecondary, marginBottom: spacing.xs },
  tVal: { ...typography.h2, color: colors.text },
  tDash: { ...typography.h3, color: colors.textMuted, paddingHorizontal: spacing.md },
  empty: { alignItems: 'center', paddingTop: spacing.xxxl * 2 },
  emTtl: { ...typography.subtitle, color: colors.text, marginBottom: spacing.sm },
  emSub: { ...typography.body, color: colors.textMuted, textAlign: 'center', marginBottom: spacing.xl },
  addBtn: { minWidth: 160 },
  overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'flex-end' },
  sheet: {
    backgroundColor: colors.white, borderTopLeftRadius: 20, borderTopRightRadius: 20,
    padding: spacing.xxl, paddingBottom: spacing.xxxl,
  },
  shTtl: { ...typography.h3, color: colors.text, marginBottom: spacing.xs },
  shDate: { ...typography.bodySmall, color: colors.textSecondary, marginBottom: spacing.xl },
  lbl: { ...typography.bodySmall, fontWeight: '600', color: colors.text, marginBottom: spacing.sm, marginTop: spacing.md },
  chips: { flexDirection: 'row', gap: spacing.sm },
  chip: {
    paddingHorizontal: spacing.md, paddingVertical: spacing.sm, borderRadius: 20,
    backgroundColor: colors.background, borderWidth: 1, borderColor: colors.border,
  },
  chipOn: { backgroundColor: colors.primary, borderColor: colors.primary },
  chipTxt: { ...typography.bodySmall, color: colors.text },
  chipTxtOn: { color: colors.white },
  acts: { flexDirection: 'row', gap: spacing.md, marginTop: spacing.xxl },
  actBtn: { flex: 1 },
});
