'use client';

import { useEffect, useState, useCallback, useRef } from 'react';
import { DateTime } from 'luxon';

interface DataItem {
  day: string;
  status: boolean;
  einheit: number;
}

interface Schema {
  curdate: string;
  months: string[];
  years: string[];
  data: DataItem[];
  einheit: number;
}

export interface SysParams {
  testing: boolean;
  doinit: boolean;
  einheit: number;
  version: string;
  date: string;
}

interface Props {
  sysParams: SysParams;
}

function CellContent({ day, einheit }: { day: DateTime; einheit: number }) {
  return (
    <div className="inner">
      {day.toFormat('d')}
      <div className="lowline small">
        <div className="wtg">{day.setLocale('de').toFormat('ccc')}</div>
        <div className="eh">{einheit !== 0 ? einheit : ''}</div>
      </div>
    </div>
  );
}

function buildMonthsLabel(s: Schema): string {
  let months = s.months.join(' - ');
  months += ' ';
  months += s.years.join('/');
  return months;
}

export default function SpritzClient({ sysParams }: Props) {
  const [schema, setSchema] = useState<Schema | null>(null);
  const [curEinheit, setCurEinheit] = useState<number>(sysParams.einheit);
  const [monthsLabel, setMonthsLabel] = useState<string>('');
  const [einheitInput, setEinheitInput] = useState<number>(sysParams.einheit);

  const schemaRef = useRef<Schema | null>(null);
  const curEinheitRef = useRef<number>(sysParams.einheit);

  schemaRef.current = schema;
  curEinheitRef.current = curEinheit;

  const apiUrl = sysParams.testing ? '/api/data?test=true' : '/api/data';

  async function fetchData(): Promise<{ data: Schema | null; err: string | null }> {
    const res = await fetch(apiUrl);
    return res.json();
  }

  async function storeData(data: Schema): Promise<unknown> {
    const response = await fetch(apiUrl, {
      method: 'POST',
      body: JSON.stringify(data),
      headers: { 'Content-Type': 'application/json' },
    });
    return response.json();
  }

  async function initSchema(startdate: string): Promise<Schema> {
    const setArray: DataItem[] = [];
    const monthArray: string[] = [];
    const yearsArray: string[] = [];
    const ld0 = DateTime.fromISO(startdate);
    let k = 0;
    for (let i = 0; i < 35; i++) {
      const elem: DataItem = { status: false, einheit: 0, day: '' };
      if (i === 17) {
        elem.day = '';
      } else {
        const ld = ld0.plus({ day: k });
        elem.day = ld.toFormat('y-LL-dd');
        const month = ld.setLocale('de').toFormat('LLLL');
        const year = ld.toFormat('y');
        if (!monthArray.includes(month)) monthArray.push(month);
        if (!yearsArray.includes(year)) yearsArray.push(year);
        k++;
      }
      setArray.push(elem);
    }
    const newSchema: Schema = {
      curdate: startdate,
      months: monthArray,
      years: yearsArray,
      data: setArray,
      einheit: curEinheitRef.current,
    };
    await storeData(newSchema);
    return newSchema;
  }

  function applySchema(s: Schema) {
    // Update einheit input to last non-zero einheit found in data
    let lastEinheit = s.einheit;
    for (const item of s.data) {
      if (item.einheit !== 0) lastEinheit = item.einheit;
    }
    if (lastEinheit !== 0 && curEinheitRef.current === 0) {
      setCurEinheit(lastEinheit);
      curEinheitRef.current = lastEinheit;
      setEinheitInput(lastEinheit);
    }
    setMonthsLabel(buildMonthsLabel(s));
    setSchema(s);
  }

  useEffect(() => {
    async function init() {
      let s: Schema | null = null;
      if (sysParams.doinit) {
        s = await initSchema('2023-05-01');
      }
      if (!s) {
        const ret = await fetchData();
        s = ret.data;
      }
      if (!s) {
        // DB leer → neues Schema mit aktuellem Datum anlegen
        const today = DateTime.now().toFormat('y-LL-dd');
        s = await initSchema(today);
      }
      if (s) {
        applySchema(s);
      }
    }
    init();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const handleClick = useCallback(async (e: React.MouseEvent<HTMLDivElement>) => {
    const button = (e.target as HTMLElement).closest('button') as HTMLButtonElement | null;
    if (!button || button.disabled) return;
    const currentSchema = schemaRef.current;
    if (!currentSchema) return;

    const idNum = parseInt(button.id.slice(2)) - 1; // 0-basierter Index
    const lastDay = currentSchema.data[34].day;

    const newSchema: Schema = {
      ...currentSchema,
      data: currentSchema.data.map((item, idx) => {
        if (idx === idNum) {
          return { ...item, status: !item.status, einheit: curEinheitRef.current };
        }
        return item;
      }),
    };

    await storeData(newSchema);
    applySchema(newSchema);

    // Letzten Button (bt35) geklickt → nächste Periode anlegen
    if (button.id === 'bt35') {
      const nextDate = DateTime.fromISO(lastDay).plus({ day: 1 }).toFormat('y-LL-dd');
      const nextSchema = await initSchema(nextDate);
      applySchema(nextSchema);
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const handleEinheitChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const val = parseInt(e.target.value) || 0;
    setCurEinheit(val);
    curEinheitRef.current = val;
    setEinheitInput(val);
    if (schemaRef.current) {
      schemaRef.current = { ...schemaRef.current, einheit: val };
    }
  }, []);

  if (!schema) {
    return <div style={{ padding: '30px' }}>Lade…</div>;
  }

  return (
    <div className="spritztab">
      <h1>Spritz-Tabelle</h1>
      <h2 id="curmon">{monthsLabel}</h2>
      <div id="sptab" onClick={handleClick}>
        {schema.data.map((item, idx) => {
          const btId = `bt${idx + 1}`;
          const day = item.day ? DateTime.fromISO(item.day) : null;
          const isDisabled = item.day === '';
          const ariaLabel = isDisabled ? 'o' : item.status ? 'x' : '';
          const displayEinheit = item.einheit !== 0 ? item.einheit : (item.status ? schema.einheit : 0);
          return (
            <button
              key={btId}
              id={btId}
              disabled={isDisabled}
              aria-label={ariaLabel}
            >
              {day && <CellContent day={day} einheit={displayEinheit} />}
            </button>
          );
        })}
      </div>
      <div id="infeld">
        <label htmlFor="einheiten">Einheiten:</label>
        <input
          id="einheiten"
          type="number"
          min={0}
          max={100}
          value={einheitInput}
          onChange={handleEinheitChange}
        />
      </div>
      <footer>
        <div id="v">
          Version {sysParams.version} vom {sysParams.date}
        </div>
      </footer>
    </div>
  );
}
