import './styles.css';
import {
  api,
  type BootstrapData,
  type CatalogoAgendar,
  type CitaCalificable,
  type CitaResumen,
  type Colaborador,
  type ServicioPrecio,
} from './api';

const tg = window.Telegram?.WebApp;
tg?.ready();
tg?.expand();

type View =
  | 'home'
  | 'register'
  | 'agendar'
  | 'citas'
  | 'precios'
  | 'info'
  | 'calificar'
  | 'comprobantes';

let bootstrap: BootstrapData | null = null;
let view: View = 'home';
let loading = true;
let error = '';

/** Estado flujo agendar */
const agendar = {
  step: 0,
  catalogo: null as CatalogoAgendar | null,
  idSucursal: 0,
  servicios: [] as number[],
  idColaborador: 0,
  dia: '',
  hora: '',
  colaboradores: [] as Colaborador[],
  dias: [] as { fecha: string }[],
  horas: [] as string[],
};

const appEl = document.getElementById('app')!;

function haptic() {
  try {
    tg?.HapticFeedback?.impactOccurred('light');
  } catch {
    /* ignore */
  }
}

function setView(v: View) {
  view = v;
  error = '';
  if (v !== 'agendar') {
    agendar.step = 0;
    agendar.catalogo = null;
  } else if (!agendar.catalogo) {
    void loadAgendarCatalogo().then(() => render());
  }
  render();
}

async function loadBootstrap() {
  loading = true;
  error = '';
  render();
  try {
    bootstrap = await api.bootstrap();
    if (!bootstrap.registrado) {
      view = 'register';
    }
  } catch (e) {
    error = e instanceof Error ? e.message : 'No se pudo conectar';
  } finally {
    loading = false;
    render();
  }
}

function navHtml(): string {
  if (!bootstrap?.registrado || view === 'register') return '';
  const items: { v: View; icon: string; label: string }[] = [
    { v: 'home', icon: '🏠', label: 'Inicio' },
    { v: 'agendar', icon: '📅', label: 'Agendar' },
    { v: 'citas', icon: '📋', label: 'Citas' },
    { v: 'precios', icon: '💰', label: 'Precios' },
    { v: 'info', icon: 'ℹ️', label: 'Info' },
  ];
  return `<nav class="nav-bottom">${items
    .map(
      (i) =>
        `<button type="button" class="nav-item ${view === i.v ? 'active' : ''}" data-nav="${i.v}">
          <span class="icon">${i.icon}</span>${i.label}
        </button>`
    )
    .join('')}</nav>`;
}

function renderRegister(): string {
  const name = bootstrap?.telegramUser?.firstName ?? '';
  return `
    <h1>¡Bienvenido!</h1>
    <p class="subtitle">${bootstrap?.empresa?.nombre ?? 'LookControl'}</p>
    ${error ? `<div class="error-box">${error}</div>` : ''}
    <p>Para agendar necesitamos tu nombre:</p>
    <input type="text" id="inp-nombre" placeholder="Nombre completo" value="${escapeHtml(name)}" maxlength="80" />
    <button type="button" class="btn" id="btn-registrar">Continuar</button>
  `;
}

function renderHome(): string {
  const b = bootstrap!;
  const o = b.opciones;
  const tiles: string[] = [];

  if (o.mostrarAgendar) {
    tiles.push(
      `<button type="button" class="menu-tile" data-go="agendar"><span class="emoji">📅</span><span>Agendar cita</span></button>`
    );
  }
  if (o.mostrarVerCitas) {
    tiles.push(
      `<button type="button" class="menu-tile" data-go="citas"><span class="emoji">📋</span><span>Mis citas</span></button>`
    );
  }
  if (o.mostrarCancelar || o.mostrarReagendar) {
    tiles.push(
      `<button type="button" class="menu-tile" data-go="citas"><span class="emoji">🔄</span><span>Reagendar / cancelar</span></button>`
    );
  }
  if (o.mostrarCalificarServicio) {
    tiles.push(
      `<button type="button" class="menu-tile" data-go="calificar"><span class="emoji">⭐</span><span>Calificar servicio</span></button>`
    );
  }
  if (o.mostrarEnviarComprobante) {
    tiles.push(
      `<button type="button" class="menu-tile" data-go="comprobantes"><span class="emoji">🧾</span><span>Enviar comprobante</span></button>`
    );
  }
  tiles.push(
    `<button type="button" class="menu-tile" data-go="precios"><span class="emoji">💰</span><span>Ver precios</span></button>`,
    `<button type="button" class="menu-tile" data-go="info"><span class="emoji">💈</span><span>Información del negocio</span></button>`
  );

  return `
    <h1>Hola, ${escapeHtml(b.cliente?.nombre ?? b.telegramUser.firstName)} 👋</h1>
    <p class="subtitle">${escapeHtml(b.empresa.nombre)}</p>
    ${!b.puedeAgendar.ok ? `<div class="error-box">${escapeHtml(b.puedeAgendar.mensaje ?? '')}</div>` : ''}
    <div class="menu-grid">${tiles.join('')}</div>
  `;
}

function stepsHtml(n: number, current: number): string {
  return `<div class="steps">${Array.from({ length: n }, (_, i) => `<div class="step-dot ${i < current ? 'done' : ''} ${i === current ? 'active' : ''}"></div>`).join('')}</div>`;
}

function renderAgendar(): string {
  if (!bootstrap?.puedeAgendar.ok) {
    return `<div class="error-box">${escapeHtml(bootstrap.puedeAgendar.mensaje ?? 'No disponible')}</div>
      <button type="button" class="btn secondary" data-go="home">Volver</button>`;
  }

  const cat = agendar.catalogo;
  if (!cat || !('ok' in cat) || !cat.ok) {
    return `<div class="loader">Cargando…</div>`;
  }

  const steps = ['Sucursal', 'Servicios', 'Colaborador', 'Día', 'Hora', 'Confirmar'];
  let body = '';

  if (agendar.step === 0) {
    body = cat.sucursales
      .map(
        (s) =>
          `<div class="card selectable ${agendar.idSucursal === s.idSucursal ? 'selected' : ''}" data-sucursal="${s.idSucursal}">
            <h3>${escapeHtml(s.nombre)}</h3>
            <p>${escapeHtml(s.direccion ?? '')}</p>
          </div>`
      )
      .join('');
  } else if (agendar.step === 1) {
    body = cat.servicios
      .map((s) => {
        const sel = agendar.servicios.includes(s.idServicio);
        return `<div class="card selectable ${sel ? 'selected' : ''}" data-servicio="${s.idServicio}">
          <h3>${escapeHtml(s.nombre)}</h3>
          <p><span class="price">$${s.precio}</span> · ${s.duracionHoras}h</p>
        </div>`;
      })
      .join('');
  } else if (agendar.step === 2) {
    body = agendar.colaboradores
      .map(
        (c) =>
          `<div class="card selectable ${agendar.idColaborador === c.idColaborador ? 'selected' : ''}" data-colab="${c.idColaborador}">
            <h3>${escapeHtml(c.nombre)}</h3>
          </div>`
      )
      .join('');
  } else if (agendar.step === 3) {
    body = `<div class="grid-2">${agendar.dias
      .map(
        (d) =>
          `<button type="button" class="chip ${agendar.dia === d.fecha ? 'selected' : ''}" data-dia="${escapeHtml(d.fecha)}">${escapeHtml(d.fecha)}</button>`
      )
      .join('')}</div>`;
  } else if (agendar.step === 4) {
    body =
      agendar.horas.length === 0
        ? `<p class="subtitle">No hay horarios disponibles este día.</p>`
        : `<div class="grid-2">${agendar.horas
            .map(
              (h) =>
                `<button type="button" class="chip ${agendar.hora === h ? 'selected' : ''}" data-hora="${escapeHtml(h)}">${formatHora(h)}</button>`
            )
            .join('')}</div>`;
  } else {
    const suc = cat.sucursales.find((s) => s.idSucursal === agendar.idSucursal);
    const col = agendar.colaboradores.find((c) => c.idColaborador === agendar.idColaborador);
    const servs = cat.servicios.filter((s) => agendar.servicios.includes(s.idServicio));
    body = `
      <div class="card">
        <h3>Resumen</h3>
        <p>📍 ${escapeHtml(suc?.nombre ?? '')}</p>
        <p>💇 ${escapeHtml(col?.nombre ?? '')}</p>
        <p>📅 ${escapeHtml(agendar.dia)} · ${formatHora(agendar.hora)}</p>
        <p>🧾 ${servs.map((s) => s.nombre).join(', ')}</p>
      </div>
      <button type="button" class="btn" id="btn-confirmar-cita">Confirmar cita</button>
    `;
  }

  return `
    <h1>Agendar cita</h1>
    ${stepsHtml(steps.length, agendar.step)}
    <p class="subtitle">Paso ${agendar.step + 1}: ${steps[agendar.step]}</p>
    ${error ? `<div class="error-box">${error}</div>` : ''}
    ${body}
    ${agendar.step > 0 ? `<button type="button" class="btn secondary" id="btn-agendar-atras">Atrás</button>` : ''}
    ${agendar.step < 5 ? `<button type="button" class="btn" id="btn-agendar-siguiente" ${canNextAgendar() ? '' : 'disabled'}>Siguiente</button>` : ''}
  `;
}

function canNextAgendar(): boolean {
  switch (agendar.step) {
    case 0:
      return agendar.idSucursal > 0;
    case 1:
      return agendar.servicios.length > 0;
    case 2:
      return agendar.idColaborador > 0;
    case 3:
      return Boolean(agendar.dia);
    case 4:
      return Boolean(agendar.hora);
    default:
      return true;
  }
}

async function loadAgendarCatalogo() {
  agendar.catalogo = await api.catalogoAgendar();
  if (!agendar.catalogo.ok) {
    error = agendar.catalogo.mensaje;
  }
}

async function agendarNext() {
  haptic();
  error = '';
  if (agendar.step === 0 && agendar.idSucursal) {
    agendar.step = 1;
  } else if (agendar.step === 1 && agendar.servicios.length) {
    agendar.colaboradores = await api.colaboradores(agendar.idSucursal);
    agendar.step = 2;
  } else if (agendar.step === 2 && agendar.idColaborador) {
    agendar.dias = await api.dias(agendar.idSucursal);
    agendar.step = 3;
  } else if (agendar.step === 3 && agendar.dia) {
    const res = await api.horas({
      idSucursal: agendar.idSucursal,
      idColaborador: agendar.idColaborador,
      dia: agendar.dia,
      servicios: agendar.servicios,
    });
    agendar.horas = res.horas;
    agendar.step = 4;
  } else if (agendar.step === 4 && agendar.hora) {
    agendar.step = 5;
  }
  render();
}

async function confirmarCita() {
  loading = true;
  render();
  try {
    const res = await api.agendar({
      idSucursal: agendar.idSucursal,
      idColaborador: agendar.idColaborador,
      dia: agendar.dia,
      hora: agendar.hora,
      servicios: agendar.servicios,
    });
    if (res.aplica) {
      appEl.innerHTML = `
        <div class="success-box">
          <h2>✅ ¡Cita confirmada!</h2>
          <p>Te enviaremos recordatorio antes de tu cita.</p>
        </div>
        <button type="button" class="btn" id="btn-ir-citas">Ver mis citas</button>
        ${navHtml()}
      `;
      bindNav();
      document.getElementById('btn-ir-citas')?.addEventListener('click', () => {
        loadBootstrap().then(() => setView('citas'));
      });
      return;
    }
    error = res.msg || 'No se pudo agendar';
  } catch (e) {
    error = e instanceof Error ? e.message : 'Error al agendar';
  } finally {
    loading = false;
    render();
  }
}

async function renderCitasAsync(container: string): Promise<string> {
  try {
    const citas = await api.citas();
    if (!citas.length) return container + `<p class="subtitle">No tienes citas registradas.</p>`;
    const cards = citas
      .map(
        (c: CitaResumen) => `
        <div class="card">
          <h3>#${c.idCita} · ${escapeHtml(c.estatus)}</h3>
          <p>📅 ${escapeHtml(c.fecha)} ${escapeHtml(c.hora)}</p>
          <p>💇 ${escapeHtml(c.colaborador)}</p>
          <p>🧾 ${escapeHtml(c.servicios)}</p>
          ${
            !/cancel/i.test(c.estatus)
              ? `<button type="button" class="btn danger btn-cancelar" data-id="${c.idCita}">Cancelar</button>`
              : ''
          }
        </div>`
      )
      .join('');
    return container + cards;
  } catch (e) {
    return container + `<div class="error-box">${e instanceof Error ? e.message : 'Error'}</div>`;
  }
}

async function renderPreciosAsync(): Promise<string> {
  const rows = await api.precios();
  const cards = rows
    .map(
      (s: ServicioPrecio) => `
      <div class="card">
        <h3>${escapeHtml(s.nombre)}</h3>
        <p class="price">$${s.precio}</p>
        ${s.descripcion ? `<p>${escapeHtml(s.descripcion)}</p>` : ''}
      </div>`
    )
    .join('');
  return `<h1>Precios</h1><p class="subtitle">Servicios disponibles</p>${cards || '<p class="subtitle">Sin servicios.</p>'}`;
}

async function renderInfoAsync(): Promise<string> {
  const info = await api.info();
  const emp = info.empresa;
  let html = `<h1>${escapeHtml(emp?.nombre ?? 'Negocio')}</h1>`;
  if (emp?.direccion) html += `<p class="subtitle">📍 ${escapeHtml(emp.direccion)}</p>`;
  if (emp?.telefono) html += `<p class="subtitle">📞 ${emp.telefono}</p>`;
  html += '<h2 style="font-size:1rem;margin-top:20px">Sucursales</h2>';
  html += info.sucursales
    .map(
      (s) =>
        `<div class="card"><h3>${escapeHtml(s.nombre)}</h3>
        <p>${escapeHtml(s.direccion ?? '')}</p>
        ${s.horario ? `<p>🕐 ${escapeHtml(s.horario)}</p>` : ''}</div>`
    )
    .join('');
  return html;
}

let calificarCitaId = 0;
let calificarStars = 0;

async function renderCalificarAsync(): Promise<string> {
  const list = await api.calificables();
  if (!list.length) {
    return `<h1>Calificar</h1><p class="subtitle">No hay citas pendientes de calificar.</p>`;
  }
  if (calificarCitaId > 0) {
    return `
      <h1>Tu opinión</h1>
      <div class="stars">${[1, 2, 3, 4, 5]
        .map((n) => `<button type="button" class="star-btn ${calificarStars >= n ? 'on' : ''}" data-star="${n}">⭐</button>`)
        .join('')}</div>
      <textarea id="inp-comentario" rows="3" placeholder="Comentario (opcional)"></textarea>
      <button type="button" class="btn" id="btn-enviar-calificacion">Enviar</button>
    `;
  }
  return (
    `<h1>Calificar servicio</h1>` +
    list
      .map(
        (c: CitaCalificable) =>
          `<div class="card selectable" data-calificar="${c.idCita}">
            <h3>Cita #${c.idCita}</h3>
            <p>${escapeHtml(c.fecha)} · ${escapeHtml(c.colaborador)}</p>
          </div>`
      )
      .join('')
  );
}

function render() {
  if (loading && view === 'home') {
    appEl.innerHTML = `<div class="loader">Cargando…</div>`;
    return;
  }

  let html = '';
  if (view === 'register') html = renderRegister();
  else if (view === 'home') html = renderHome();
  else if (view === 'agendar') html = renderAgendar();
  else if (view === 'citas') html = `<h1>Mis citas</h1><div class="loader">Cargando…</div>`;
  else if (view === 'precios') html = `<div class="loader">Cargando…</div>`;
  else if (view === 'info') html = `<div class="loader">Cargando…</div>`;
  else if (view === 'calificar') html = `<div class="loader">Cargando…</div>`;
  else if (view === 'comprobantes') {
    html = `<h1>Comprobantes</h1><p class="subtitle">Por ahora usa el bot de Telegram para enviar la foto del comprobante. Próximamente aquí.</p>
      <button type="button" class="btn secondary" data-go="home">Volver</button>`;
  }

  appEl.innerHTML = html + navHtml();
  bindNav();
  bindRegister();
  bindHome();
  bindAgendar();

  if (view === 'citas') {
    void renderCitasAsync('<h1>Mis citas</h1><p class="subtitle">Tus reservas</p>').then((h) => {
      appEl.innerHTML = h + navHtml();
      bindNav();
      bindCancelar();
    });
  }
  if (view === 'precios') {
    void renderPreciosAsync().then((h) => {
      appEl.innerHTML = h + navHtml();
      bindNav();
    });
  }
  if (view === 'info') {
    void renderInfoAsync().then((h) => {
      appEl.innerHTML = h + navHtml();
      bindNav();
    });
  }
  if (view === 'calificar') {
    void renderCalificarAsync().then((h) => {
      appEl.innerHTML = h + navHtml();
      bindNav();
      bindCalificar();
    });
  }
}

function bindNav() {
  document.querySelectorAll('[data-nav]').forEach((el) => {
    el.addEventListener('click', () => {
      const v = (el as HTMLElement).dataset.nav as View;
      haptic();
      if (v === 'agendar') {
        agendar.step = 0;
        agendar.idSucursal = 0;
        agendar.servicios = [];
        void loadAgendarCatalogo().then(() => setView('agendar'));
      } else {
        setView(v);
      }
    });
  });
  document.querySelectorAll('[data-go]').forEach((el) => {
    el.addEventListener('click', () => {
      const v = (el as HTMLElement).dataset.go as View;
      haptic();
      if (v === 'agendar') {
        void loadAgendarCatalogo().then(() => setView('agendar'));
      } else {
        setView(v);
      }
    });
  });
}

function bindRegister() {
  document.getElementById('btn-registrar')?.addEventListener('click', async () => {
    const nombre = (document.getElementById('inp-nombre') as HTMLInputElement)?.value?.trim();
    if (!nombre || nombre.length < 3) {
      error = 'Nombre muy corto';
      render();
      return;
    }
    loading = true;
    render();
    try {
      bootstrap = await api.registrar(nombre);
      view = 'home';
    } catch (e) {
      error = e instanceof Error ? e.message : 'Error';
    } finally {
      loading = false;
      render();
    }
  });
}

function bindHome() {
  /* data-go en bindNav */
}

function bindAgendar() {
  document.querySelectorAll('[data-sucursal]').forEach((el) => {
    el.addEventListener('click', () => {
      agendar.idSucursal = Number((el as HTMLElement).dataset.sucursal);
      haptic();
      render();
    });
  });
  document.querySelectorAll('[data-servicio]').forEach((el) => {
    el.addEventListener('click', () => {
      const id = Number((el as HTMLElement).dataset.servicio);
      const i = agendar.servicios.indexOf(id);
      if (i >= 0) agendar.servicios.splice(i, 1);
      else agendar.servicios.push(id);
      haptic();
      render();
    });
  });
  document.querySelectorAll('[data-colab]').forEach((el) => {
    el.addEventListener('click', () => {
      agendar.idColaborador = Number((el as HTMLElement).dataset.colab);
      haptic();
      render();
    });
  });
  document.querySelectorAll('[data-dia]').forEach((el) => {
    el.addEventListener('click', () => {
      agendar.dia = (el as HTMLElement).dataset.dia ?? '';
      haptic();
      render();
    });
  });
  document.querySelectorAll('[data-hora]').forEach((el) => {
    el.addEventListener('click', () => {
      agendar.hora = (el as HTMLElement).dataset.hora ?? '';
      haptic();
      render();
    });
  });
  document.getElementById('btn-agendar-siguiente')?.addEventListener('click', () => void agendarNext());
  document.getElementById('btn-agendar-atras')?.addEventListener('click', () => {
    if (agendar.step > 0) agendar.step--;
    render();
  });
  document.getElementById('btn-confirmar-cita')?.addEventListener('click', () => void confirmarCita());
}

function bindCancelar() {
  document.querySelectorAll('.btn-cancelar').forEach((el) => {
    el.addEventListener('click', async () => {
      const id = Number((el as HTMLElement).dataset.id);
      if (!confirm('¿Cancelar esta cita?')) return;
      try {
        await api.cancelar(id);
        setView('citas');
      } catch (e) {
        alert(e instanceof Error ? e.message : 'Error');
      }
    });
  });
}

function bindCalificar() {
  document.querySelectorAll('[data-calificar]').forEach((el) => {
    el.addEventListener('click', () => {
      calificarCitaId = Number((el as HTMLElement).dataset.calificar);
      calificarStars = 0;
      render();
    });
  });
  document.querySelectorAll('.star-btn').forEach((el) => {
    el.addEventListener('click', () => {
      calificarStars = Number((el as HTMLElement).dataset.star);
      render();
    });
  });
  document.getElementById('btn-enviar-calificacion')?.addEventListener('click', async () => {
    if (calificarStars < 1) {
      alert('Elige una calificación');
      return;
    }
    const comentario = (document.getElementById('inp-comentario') as HTMLTextAreaElement)?.value ?? '';
    try {
      await api.calificar(calificarCitaId, calificarStars, comentario);
      calificarCitaId = 0;
      alert('¡Gracias!');
      setView('home');
    } catch (e) {
      alert(e instanceof Error ? e.message : 'Error');
    }
  });
}

function escapeHtml(s: string): string {
  return s
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

function formatHora(h: string): string {
  const parts = h.split(':').map(Number);
  const hh = parts[0] ?? 0;
  const mm = parts[1] ?? 0;
  const ampm = hh >= 12 ? 'PM' : 'AM';
  const h12 = hh % 12 || 12;
  return `${h12}:${String(mm).padStart(2, '0')} ${ampm}`;
}

void loadBootstrap();
