/**
 * TeamsBot Modules View
 *
 * CRUD list of MeetingModules with expandable session lists per module.
 */
import React, { useState, useEffect, useCallback, useRef } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useCurrentInstance } from '../../../hooks/useCurrentInstance';
import * as teamsbotApi from '../../../api/teamsbotApi';
import type { MeetingModule, TeamsbotSession, MediaFileInfo } from '../../../api/teamsbotApi';
import { useLanguage } from '../../../providers/language/LanguageContext';
import { useFileContext } from '../../../contexts/FileContext';
import { FaSpinner } from 'react-icons/fa';
import styles from './Teamsbot.module.css';

const SERIES_TYPE_LABELS: Record<string, string> = {
  weekly: 'Wöchentlich',
  biweekly: 'Zweiwöchentlich',
  monthly: 'Monatlich',
  adhoc: 'Adhoc',
  project: 'Projekt',
};

const STATUS_LABELS: Record<string, string> = {
  active: 'Aktiv',
  archived: 'Archiviert',
  completed: 'Abgeschlossen',
};

export const TeamsbotModulesView: React.FC = () => {
  const { t } = useLanguage();
  const { instance, mandateId } = useCurrentInstance();
  const instanceId = instance?.id || '';
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const focusModuleId = searchParams.get('moduleId') || '';
  const moduleRowRefs = useRef<Record<string, HTMLDivElement | null>>({});

  const [modules, setModules] = useState<MeetingModule[]>([]);
  const [loading, setLoading] = useState(true);
  const [expandedId, setExpandedId] = useState<string | null>(null);
  const [moduleSessions, setModuleSessions] = useState<Record<string, TeamsbotSession[]>>({});
  const [deleteConfirm, setDeleteConfirm] = useState<string | null>(null);
  const [editingModule, setEditingModule] = useState<MeetingModule | null>(null);
  const [createOpen, setCreateOpen] = useState(false);
  const [createTitle, setCreateTitle] = useState('');
  const [createSeriesType, setCreateSeriesType] = useState<string>('adhoc');
  const [createDefaultLink, setCreateDefaultLink] = useState('');
  const [createDefaultBotName, setCreateDefaultBotName] = useState('');
  const [createGoals, setCreateGoals] = useState('');
  const [createDefaultAvatarFileId, setCreateDefaultAvatarFileId] = useState('');
  const [createSaving, setCreateSaving] = useState(false);

  const [mediaFiles, setMediaFiles] = useState<MediaFileInfo[]>([]);
  const fileCtx = useFileContext();
  const avatarInputRef = useRef<HTMLInputElement | null>(null);
  const [avatarUploading, setAvatarUploading] = useState(false);
  const [avatarTarget, setAvatarTarget] = useState<'create' | 'edit'>('create');

  const _refreshMediaFiles = useCallback(async () => {
    const result = await teamsbotApi.listMediaFiles().catch(() => [] as MediaFileInfo[]);
    setMediaFiles(result);
  }, []);

  const _handleAvatarUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file || !fileCtx?.handleFileUpload) return;
    setAvatarUploading(true);
    try {
      const result = await fileCtx.handleFileUpload(file);
      if (result?.success) {
        const data: any = (result.fileData as any)?.file || result.fileData;
        const id = data?.id || (result.fileData as any)?.id;
        if (id) {
          if (avatarTarget === 'create') {
            setCreateDefaultAvatarFileId(id);
          } else if (editingModule) {
            setEditingModule({ ...editingModule, defaultAvatarFileId: id });
          }
          const refreshed = await teamsbotApi.listMediaFiles().catch(() => [] as MediaFileInfo[]);
          setMediaFiles(refreshed);
        }
      }
    } catch {
      // upload error handled by FileContext
    } finally {
      setAvatarUploading(false);
      if (avatarInputRef.current) avatarInputRef.current.value = '';
    }
  };

  const _loadModules = useCallback(async () => {
    if (!instanceId) return;
    setLoading(true);
    try {
      const result = await teamsbotApi.listModules(instanceId);
      setModules(result || []);
    } catch (err) {
      console.error('Failed to load modules:', err);
    } finally {
      setLoading(false);
    }
  }, [instanceId]);

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

  useEffect(() => {
    teamsbotApi.listMediaFiles().then(setMediaFiles).catch(() => {});
  }, []);

  const _loadModuleSessions = useCallback(async (moduleId: string) => {
    if (!instanceId) return;
    try {
      const detail = await teamsbotApi.getModuleDetail(instanceId, moduleId);
      setModuleSessions(prev => ({ ...prev, [moduleId]: detail?.sessions || [] }));
    } catch (err) {
      console.error('Failed to load module sessions:', err);
    }
  }, [instanceId]);

  useEffect(() => {
    if (!focusModuleId || modules.length === 0) return;
    if (!modules.some((m) => m.id === focusModuleId)) return;
    setExpandedId(focusModuleId);
    _loadModuleSessions(focusModuleId);
  }, [focusModuleId, modules, _loadModuleSessions]);

  useEffect(() => {
    if (!focusModuleId || expandedId !== focusModuleId) return;
    requestAnimationFrame(() => {
      moduleRowRefs.current[focusModuleId]?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
    });
  }, [focusModuleId, expandedId]);

  const _toggleExpand = (moduleId: string) => {
    if (expandedId === moduleId) {
      setExpandedId(null);
    } else {
      setExpandedId(moduleId);
      if (!moduleSessions[moduleId]) _loadModuleSessions(moduleId);
    }
  };

  const _handleDelete = async (moduleId: string) => {
    try {
      await teamsbotApi.deleteModule(instanceId, moduleId);
      setDeleteConfirm(null);
      _loadModules();
    } catch (err) {
      console.error('Delete failed:', err);
    }
  };

  const _handleUpdate = async (moduleId: string, updates: Partial<MeetingModule>) => {
    try {
      await teamsbotApi.updateModule(instanceId, moduleId, updates);
      setEditingModule(null);
      _loadModules();
    } catch (err) {
      console.error('Update failed:', err);
    }
  };

  const _handleCreateModule = async () => {
    if (!createTitle.trim()) return;
    setCreateSaving(true);
    try {
      await teamsbotApi.createModule(instanceId, {
        title: createTitle.trim(),
        seriesType: createSeriesType,
        defaultMeetingLink: createDefaultLink.trim() || undefined,
        defaultBotName: createDefaultBotName.trim() || undefined,
        defaultAvatarFileId: createDefaultAvatarFileId || undefined,
        goals: createGoals.trim() || undefined,
      });
      setCreateOpen(false);
      setCreateTitle('');
      setCreateSeriesType('adhoc');
      setCreateDefaultLink('');
      setCreateDefaultBotName('');
      setCreateDefaultAvatarFileId('');
      setCreateGoals('');
      _loadModules();
    } catch (err) {
      console.error('Create module failed:', err);
    } finally {
      setCreateSaving(false);
    }
  };

  const _formatSessionDateTime = (ts?: string | number): string => {
    if (ts == null) return '-';
    const ms = typeof ts === 'number' ? ts * 1000 : Date.parse(String(ts));
    if (Number.isNaN(ms)) return '-';
    const d = new Date(ms);
    const pad = (n: number) => String(n).padStart(2, '0');
    return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
  };

  const _calcDurationMin = (startedAt?: string | number, endedAt?: string | number): string => {
    if (!startedAt) return '-';
    const startMs = typeof startedAt === 'number' ? startedAt * 1000 : Date.parse(String(startedAt));
    if (Number.isNaN(startMs)) return '-';
    const endMs = endedAt
      ? (typeof endedAt === 'number' ? endedAt * 1000 : Date.parse(String(endedAt)))
      : Date.now();
    if (Number.isNaN(endMs)) return '-';
    const mins = Math.round((endMs - startMs) / 60000);
    return `${mins} min`;
  };

  const _sortedSessions = (sessions: TeamsbotSession[]): TeamsbotSession[] =>
    [...sessions].sort((a, b) => {
      const ta = a.startedAt ? (typeof a.startedAt === 'number' ? a.startedAt * 1000 : Date.parse(String(a.startedAt))) : 0;
      const tb = b.startedAt ? (typeof b.startedAt === 'number' ? b.startedAt * 1000 : Date.parse(String(b.startedAt))) : 0;
      return tb - ta;
    });

  return (
    <div className={styles.modulesContainer}>
      <div className={styles.modulesHeader}>
        <h2>{t('Meeting-Module')}</h2>
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.5rem' }}>
          <button
            type="button"
            className={styles.btnSecondary}
            onClick={() => setCreateOpen(true)}
          >
            {t('Modul anlegen')}
          </button>
          <button
            type="button"
            className={styles.btnPrimary}
            onClick={() => navigate(`/mandates/${mandateId}/teamsbot/${instanceId}/assistant`)}
          >
            {t('Meeting starten')}
          </button>
        </div>
      </div>

      {loading && <div className={styles.loading}>{t('Laden...')}</div>}

      <div className={styles.modulesList}>
        {modules.map(mod => (
          <div
            key={mod.id}
            ref={(el) => { moduleRowRefs.current[mod.id] = el; }}
            className={`${styles.moduleCard} ${expandedId === mod.id ? styles.moduleExpanded : ''} ${focusModuleId === mod.id ? styles.moduleRowFocused : ''}`}
          >
            <div className={styles.moduleRow} onClick={() => _toggleExpand(mod.id)}>
              <span className={styles.moduleType}>{t(SERIES_TYPE_LABELS[mod.seriesType] || mod.seriesType)}</span>
              <span className={styles.moduleTitle}>{mod.title}</span>
              <span className={styles.moduleStatus}>{t(STATUS_LABELS[mod.status] || mod.status || 'Aktiv')}</span>
              <div className={styles.moduleActions}>
                <button className={styles.btnPrimary} style={{ padding: '0.3rem 0.7rem', fontSize: '0.8rem' }} onClick={e => {
                  e.stopPropagation();
                  navigate(`/mandates/${mandateId}/teamsbot/${instanceId}/assistant?moduleId=${mod.id}`);
                }}>{t('Meeting starten')}</button>
                <button className={styles.btnSmall} onClick={e => { e.stopPropagation(); setEditingModule(mod); }}>{t('Bearbeiten')}</button>
                <button className={styles.btnSmallDanger} onClick={e => { e.stopPropagation(); setDeleteConfirm(mod.id); }}>{t('Löschen')}</button>
              </div>
            </div>

            {expandedId === mod.id && (
              <div className={styles.moduleSessionsList}>
                {(moduleSessions[mod.id] || []).length === 0 ? (
                  <p className={styles.noSessions}>{t('Keine Sitzungen')}</p>
                ) : (
                  <table className={styles.sessionTable}>
                    <thead>
                      <tr>
                        <th style={{ width: 32 }}></th>
                        <th>{t('Datum')}</th>
                        <th>{t('Dauer')}</th>
                        <th>{t('Status')}</th>
                      </tr>
                    </thead>
                    <tbody>
                      {_sortedSessions(moduleSessions[mod.id] || []).map((sess) => (
                        <tr
                          key={sess.id}
                          className={styles.sessionTableRow}
                          onClick={() => navigate(`/mandates/${mandateId}/teamsbot/${instanceId}/sessions?sessionId=${sess.id}`)}
                        >
                          <td>
                            <button
                              type="button"
                              className={styles.sessionDeleteBtn}
                              title={t('Sitzung loeschen')}
                              onClick={async (e) => {
                                e.stopPropagation();
                                try {
                                  await teamsbotApi.deleteSession(instanceId, sess.id);
                                  setModuleSessions((prev) => ({
                                    ...prev,
                                    [mod.id]: (prev[mod.id] || []).filter((s) => s.id !== sess.id),
                                  }));
                                } catch (err) {
                                  console.error('Delete session failed:', err);
                                }
                              }}
                            >
                              x
                            </button>
                          </td>
                          <td>{_formatSessionDateTime(sess.startedAt)}</td>
                          <td>{_calcDurationMin(sess.startedAt, sess.endedAt)}</td>
                          <td><span className={styles.sessionStatus}>{sess.status}</span></td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                )}
              </div>
            )}
          </div>
        ))}
      </div>

      {createOpen && (
        <div className={styles.confirmOverlay}>
          <div className={styles.editDialog}>
            <h3>{t('Modul anlegen')}</h3>
            <label className={styles.label}>{t('Titel')}</label>
            <input
              type="text"
              className={styles.wizardInput}
              value={createTitle}
              onChange={e => setCreateTitle(e.target.value)}
              placeholder={t('z.B. Weekly Standup')}
              autoFocus
            />
            <label className={styles.label} style={{ display: 'block', marginTop: 8 }}>{t('Serientyp')}</label>
            <select
              className={styles.wizardSelect}
              value={createSeriesType}
              onChange={e => setCreateSeriesType(e.target.value)}
            >
              {Object.entries(SERIES_TYPE_LABELS).map(([code, lab]) => (
                <option key={code} value={code}>{lab}</option>
              ))}
            </select>
            <label className={styles.label} style={{ display: 'block', marginTop: 8 }}>{t('Standard-Meeting-Link')}</label>
            <input
              type="text"
              className={styles.wizardInput}
              value={createDefaultLink}
              onChange={e => setCreateDefaultLink(e.target.value)}
              placeholder="https://teams.microsoft.com/..."
            />
            <label className={styles.label} style={{ display: 'block', marginTop: 8 }}>{t('Standard-Bot-Name')}</label>
            <input
              type="text"
              className={styles.wizardInput}
              value={createDefaultBotName}
              onChange={e => setCreateDefaultBotName(e.target.value)}
            />
            <label className={styles.label} style={{ display: 'block', marginTop: 8 }}>{t('Avatar-Bild / Video')}</label>
            <div style={{ display: 'flex', gap: '6px', alignItems: 'center' }}>
              <select
                className={styles.wizardSelect}
                style={{ flex: 1 }}
                value={createDefaultAvatarFileId}
                onChange={e => setCreateDefaultAvatarFileId(e.target.value)}
                onFocus={_refreshMediaFiles}
              >
                <option value="">{t('Standard (aus Bot-Einstellungen)')}</option>
                {mediaFiles.map(f => (
                  <option key={f.id} value={f.id}>{f.fileName} ({f.mimeType})</option>
                ))}
              </select>
              <button type="button" className={styles.btnSmall} disabled={avatarUploading} onClick={() => { setAvatarTarget('create'); avatarInputRef.current?.click(); }} style={{ whiteSpace: 'nowrap' }}>
                {avatarUploading && avatarTarget === 'create' ? <FaSpinner className={styles.spinner} /> : null}
                {t('Hochladen')}
              </button>
            </div>
            <label className={styles.label} style={{ display: 'block', marginTop: 8 }}>{t('Ziele')}</label>
            <textarea
              className={styles.wizardTextarea}
              rows={2}
              value={createGoals}
              onChange={e => setCreateGoals(e.target.value)}
            />
            <div className={styles.confirmActions}>
              <button type="button" className={styles.btnSecondary} onClick={() => setCreateOpen(false)}>{t('Abbrechen')}</button>
              <button
                type="button"
                className={styles.btnPrimary}
                onClick={_handleCreateModule}
                disabled={!createTitle.trim() || createSaving}
              >
                {createSaving ? t('Speichern…') : t('Anlegen')}
              </button>
            </div>
          </div>
        </div>
      )}

      {deleteConfirm && (
        <div className={styles.confirmOverlay}>
          <div className={styles.confirmDialog}>
            <p>{t('Modul wirklich löschen? Sessions werden dem Modul entkoppelt.')}</p>
            <div className={styles.confirmActions}>
              <button className={styles.btnSecondary} onClick={() => setDeleteConfirm(null)}>{t('Abbrechen')}</button>
              <button className={styles.btnDanger} onClick={() => _handleDelete(deleteConfirm)}>{t('Löschen')}</button>
            </div>
          </div>
        </div>
      )}

      {editingModule && (
        <div className={styles.confirmOverlay}>
          <div className={styles.editDialog}>
            <h3>{t('Modul bearbeiten')}</h3>
            <input
              type="text"
              defaultValue={editingModule.title}
              className={styles.wizardInput}
              onBlur={e => setEditingModule({ ...editingModule, title: e.target.value })}
            />
            <label className={styles.label} style={{ display: 'block', marginTop: 8 }}>{t('Standard-Meeting-Link')}</label>
            <input
              type="text"
              defaultValue={editingModule.defaultMeetingLink || ''}
              className={styles.wizardInput}
              placeholder="https://teams.microsoft.com/l/meetup-join/..."
              onBlur={e => setEditingModule({ ...editingModule, defaultMeetingLink: e.target.value })}
            />
            <label className={styles.label} style={{ display: 'block', marginTop: 8 }}>{t('Standard-Bot-Name')}</label>
            <input
              type="text"
              defaultValue={editingModule.defaultBotName || ''}
              className={styles.wizardInput}
              placeholder={t('z.B. AI Assistant')}
              onBlur={e => setEditingModule({ ...editingModule, defaultBotName: e.target.value })}
            />
            <label className={styles.label} style={{ display: 'block', marginTop: 8 }}>{t('Avatar-Bild / Video')}</label>
            <div style={{ display: 'flex', gap: '6px', alignItems: 'center' }}>
            <select
              className={styles.wizardSelect}
              style={{ flex: 1 }}
              value={editingModule.defaultAvatarFileId || ''}
              onChange={e => setEditingModule({ ...editingModule, defaultAvatarFileId: e.target.value || undefined })}
              onFocus={_refreshMediaFiles}
            >
              <option value="">{t('Standard (aus Bot-Einstellungen)')}</option>
              {mediaFiles.map(f => (
                <option key={f.id} value={f.id}>{f.fileName} ({f.mimeType})</option>
              ))}
            </select>
              <button type="button" className={styles.btnSmall} disabled={avatarUploading} onClick={() => { setAvatarTarget('edit'); avatarInputRef.current?.click(); }} style={{ whiteSpace: 'nowrap' }}>
                {avatarUploading && avatarTarget === 'edit' ? <FaSpinner className={styles.spinner} /> : null}
                {t('Hochladen')}
              </button>
            </div>
            <textarea
              defaultValue={editingModule.goals || ''}
              className={styles.wizardTextarea}
              placeholder={t('Ziele')}
              rows={3}
              onBlur={e => setEditingModule({ ...editingModule, goals: e.target.value })}
            />
            <div className={styles.confirmActions}>
              <button className={styles.btnSecondary} onClick={() => setEditingModule(null)}>{t('Abbrechen')}</button>
              <button className={styles.btnPrimary} onClick={() => _handleUpdate(editingModule.id, {
                title: editingModule.title,
                goals: editingModule.goals,
                defaultMeetingLink: (editingModule.defaultMeetingLink || '').trim(),
                defaultBotName: (editingModule.defaultBotName || '').trim(),
                defaultAvatarFileId: (editingModule.defaultAvatarFileId || '').trim() || undefined,
              })}>{t('Speichern')}</button>
            </div>
          </div>
        </div>
      )}

      <input
        ref={avatarInputRef}
        type="file"
        accept="image/*,video/*"
        style={{ display: 'none' }}
        onChange={_handleAvatarUpload}
      />
    </div>
  );
};
