import { CalendarApp } from './CalendarApp.js';
import { CalendarConfigDialog } from './CalendarConfigDialog.js';
import { JournalNoteDialog } from './JournalNoteDialog.js';
import { getDefaultCalendar, formatImperialDate, formatRealDate } from './calendarDate.js';

const MODULE_ID = 'mgt2-compendium-amiral-denisov';
const ChatLogV2 = foundry.applications.sidebar.tabs.ChatLog;

let _calendarApp = null;

function readCalendar() {
  return {
    year: game.settings.get(MODULE_ID, 'calendarYear'),
    day: game.settings.get(MODULE_ID, 'calendarDay'),
    hour: game.settings.get(MODULE_ID, 'calendarHour'),
    minute: game.settings.get(MODULE_ID, 'calendarMinute'),
    planet: game.settings.get(MODULE_ID, 'calendarPlanet'),
  };
}

async function writeCalendar(data) {
  await game.settings.set(MODULE_ID, 'calendarYear', data.year);
  await game.settings.set(MODULE_ID, 'calendarDay', data.day);
  await game.settings.set(MODULE_ID, 'calendarHour', data.hour);
  await game.settings.set(MODULE_ID, 'calendarMinute', data.minute);
  await game.settings.set(MODULE_ID, 'calendarPlanet', data.planet);
}

function applyCalendar(data) {
  if (_calendarApp) {
    _calendarApp.updateDisplay(data);
  }
}

async function broadcastCalendar(data) {
  if (!game.socket?.emit) return;
  game.socket.emit(`module.${MODULE_ID}`, {
    _type: 'calendarSync',
    ...data,
  });
}

function openCalendarApp() {
  if (_calendarApp) {
    _calendarApp.bringToTop();
    return;
  }
  const data = readCalendar();
  _calendarApp = new CalendarApp({
    onConfig: () => openCalendarConfig(),
    onNote: () => openJournalNote(),
    onClose: () => { _calendarApp = null; },
  });
  _calendarApp.updateDisplay(data);
  _calendarApp.render({ force: true });
}

function openCalendarConfig() {
  const data = readCalendar();
  const dialog = new CalendarConfigDialog({
    data,
    onApply: async (newData) => {
      await writeCalendar(newData);
      applyCalendar(newData);
      broadcastCalendar(newData);
      dialog.close();
    },
  });
  dialog.render({ force: true });
}

async function appendJournalNote(content, { dateLabel, realLabel } = {}) {
  if (!content) return false;
  const journalName = game.settings.get(MODULE_ID, 'calendarJournalName') || 'Journal de bord';
  let journal = game.journal.getName(journalName);
  if (!journal) {
    journal = await JournalEntry.create({ name: journalName });
    if (!journal) {
      ui.notifications.error('Impossible de créer le journal');
      return false;
    }
  }
  if (!dateLabel || !realLabel) {
    const c = readCalendar();
    dateLabel = formatImperialDate(c);
    realLabel = formatRealDate();
  }
  const safeContent = $('<div>').text(content).html().replace(/\n/g, '<br>');
  const noteHtml = `<hr>
<h3>${realLabel} — ${dateLabel}</h3>
<p>${safeContent}</p>`;
  let page = journal.pages.contents[0];
  if (!page) {
    [page] = await journal.createEmbeddedDocuments('JournalEntryPage', [{ name: 'Notes', text: { content: '' } }]);
  }
  if (!page) {
    ui.notifications.error('Impossible de créer une page dans le journal');
    return false;
  }
  const existing = page.text?.content || '';
  await page.update({ 'text.content': existing + '\n' + noteHtml });
  ui.notifications.info(`Note ajoutée au journal « ${journalName} »`);
  return true;
}

function openJournalNote() {
  const calendar = readCalendar();
  const dateLabel = formatImperialDate(calendar);
  const realLabel = formatRealDate();
  const dialog = new JournalNoteDialog({
    imperialDate: dateLabel,
    realDate: realLabel,
    onSave: async (content) => {
      const ok = await appendJournalNote(content, { dateLabel, realLabel });
      if (ok) dialog.close();
    },
  });
  dialog.render({ force: true });
}

function registerCalCommand() {
  if (!ChatLogV2?.CHAT_COMMANDS) return;
  ChatLogV2.CHAT_COMMANDS.cal = {
    rgx: /^\/cal(?:\s+(.*))?$/i,
    fn: () => {
      openCalendarApp();
      return false;
    },
  };
  console.log(`${MODULE_ID} | Commande /cal enregistrée via ChatLog.CHAT_COMMANDS`);
}

Hooks.once('init', () => {
  const def = getDefaultCalendar();

  game.settings.register(MODULE_ID, 'calendarYear', {
    name: 'Année impériale',
    scope: 'world',
    config: false,
    type: Number,
    default: def.year,
  });
  game.settings.register(MODULE_ID, 'calendarDay', {
    name: 'Jour impérial (1-365)',
    scope: 'world',
    config: false,
    type: Number,
    default: def.day,
  });
  game.settings.register(MODULE_ID, 'calendarHour', {
    name: 'Heure locale',
    scope: 'world',
    config: false,
    type: Number,
    default: def.hour,
  });
  game.settings.register(MODULE_ID, 'calendarMinute', {
    name: 'Minute locale',
    scope: 'world',
    config: false,
    type: Number,
    default: def.minute,
  });
  game.settings.register(MODULE_ID, 'calendarPlanet', {
    name: 'Planète',
    scope: 'world',
    config: false,
    type: String,
    default: def.planet,
  });
  game.settings.register(MODULE_ID, 'calendarAutoOpen', {
    name: 'Calendrier impérial : auto-ouverture',
    hint: 'Ouvre automatiquement la fenêtre du calendrier au démarrage',
    scope: 'world',
    config: true,
    type: Boolean,
    default: true,
  });
  game.settings.register(MODULE_ID, 'calendarJournalName', {
    name: 'Journal de bord',
    hint: 'Nom du journal utilisé pour les notes de session. Créé automatiquement s\'il n\'existe pas.',
    scope: 'world',
    config: true,
    type: String,
    default: 'Journal de bord',
  });
  game.settings.register(MODULE_ID, 'calendarPosition', {
    scope: 'client',
    config: false,
    type: Object,
    default: {},
  });

  const loadTemplatesFn = foundry.applications?.handlebars?.loadTemplates || loadTemplates;
  if (loadTemplatesFn) {
    loadTemplatesFn([
      `modules/${MODULE_ID}/templates/calendar-app.hbs`,
      `modules/${MODULE_ID}/templates/calendar-config.hbs`,
      `modules/${MODULE_ID}/templates/journal-note-dialog.hbs`,
    ]);
  }

  registerCalCommand();
  console.log(`${MODULE_ID} | Calendrier impérial initialisé`);
});

Hooks.once('ready', () => {
  game.socket.on(`module.${MODULE_ID}`, (data) => {
    if (game.user?.isGM) return;
    if (data?._type !== 'calendarSync') return;
    if (!_calendarApp) {
      const { year, day, hour, minute, planet } = data;
      _calendarApp = new CalendarApp({
        onClose: () => { _calendarApp = null; },
      });
      _calendarApp.updateDisplay({ year, day, hour, minute, planet });
      _calendarApp.render({ force: true });
      return;
    }
    _calendarApp.updateDisplay(data);
  });

  if (game.settings.get(MODULE_ID, 'calendarAutoOpen')) {
    openCalendarApp();
  }
});

Hooks.on('preCreateChatMessage', (message, data, options) => {
  const content = message.content?.trim()?.toLowerCase();
  if (content === '/cal' || content?.startsWith('/cal ')) {
    openCalendarApp();
    return false;
  }
});

Hooks.on('chatMessage', (...args) => {
  let message;
  if (args[0]?.content !== undefined) {
    message = args[0].content;
  } else if (typeof args[1] === 'string') {
    message = args[1];
  } else {
    return;
  }
  const trimmed = message?.trim()?.toLowerCase();
  if (trimmed === '/cal' || trimmed?.startsWith('/cal ')) {
    openCalendarApp();
    return false;
  }
});

Hooks.on('renderChatInput', (app, html, data) => {
  let input;
  if (html?.element) {
    input = $(html.element).find('textarea[name="content"]');
  } else if (html?.find) {
    input = html.find('textarea[name="content"]');
  } else {
    input = $(html).find('textarea[name="content"]');
  }
  if (input.data('mgt2-cal-listener')) return;
  input.data('mgt2-cal-listener', true);
  input.on('keydown', (event) => {
    if (event.key === 'Enter' && !event.shiftKey) {
      const content = input.val()?.trim();
      if (content === '/cal' || content?.startsWith('/cal ')) {
        event.preventDefault();
        event.stopImmediatePropagation();
        openCalendarApp();
        input.val('');
      }
    }
  });
});
