import {
  Component,
  OnInit,
  ChangeDetectorRef,
  ViewChild,
  ElementRef
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { finalize } from 'rxjs/operators';

import Chart from 'chart.js/auto';

import {
  PacienteService,
  Paciente,
  Cita,
  Especialidad,
  NuevaCita
} from './servicios/paciente';

import {
  ImportacionService,
  EstadoImportacion,
  RespuestaImportacion,
  HistogramaPaciente,
  HistogramaGeneral,
  HistPacienteMes
} from './servicios/importacion';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './app.html',
  styleUrls: ['./app.css'],
})
export class AppComponent implements OnInit {
  titulo = 'AUNAR Salud';

  tipoBusqueda: 'documento' | 'nombre' = 'documento';

  termino = '';
  cargando = false;
  error: string | null = null;

  pacientes: Paciente[] = [];

  pacienteSeleccionado: Paciente | null = null;
  citas: Cita[] = [];
  cargandoCitas = false;

  especialidades: Especialidad[] = [];

  // formulario de nueva cita
  formCita = {
    id_especialidad: '',
    fecha_cita: '',
    hora_cita: '',
    tipo_cita: '',
    observaciones: '',
    modalidad: ''
  };

  guardandoCita = false;
  mensajeCita: string | null = null;
  errorCita: string | null = null;

  // edición asistencia
  guardandoAsistenciaId: number | null = null;
  errorAsistencia: string | null = null;

  // --- IMPORTACIÓN EXCEL ---
  estadoImport: EstadoImportacion | null = null;
  cargandoImport = false;
  subiendoPlanilla = false;
  subiendoHistor = false;
  sincronizando = false;
  mensajeImport: string | null = null;

  logImport: string[] = [];
  errorImport: string | null = null;

  archivoPlanilla: File | null = null;
  archivoHistor: File | null = null;

  // --- HISTOGRAMAS ---
  histPaciente: HistogramaPaciente | null = null;
  cargandoHistPaciente = false;
  errorHistPaciente: string | null = null;

  histGeneral: HistogramaGeneral | null = null;
  cargandoHistGeneral = false;
  errorHistGeneral: string | null = null;

  // --- CANVAS CHARTS ---
  @ViewChild('canvasGeneralEsp') canvasGeneralEsp!: ElementRef<HTMLCanvasElement>;
  @ViewChild('canvasGeneralMes') canvasGeneralMes!: ElementRef<HTMLCanvasElement>;
  @ViewChild('canvasPaciente') canvasPaciente!: ElementRef<HTMLCanvasElement>;

  private grafGeneralEsp: Chart | null = null;
  private grafGeneralMes: Chart | null = null;
  private grafPaciente: Chart | null = null;

  constructor(
    private pacienteService: PacienteService,
    private importacionService: ImportacionService,
    private cdr: ChangeDetectorRef
  ) {}

  ngOnInit(): void {
    this.cargando = true;
    this.error = null;

    // Pacientes iniciales
    this.pacienteService
      .listarPacientes()
      .pipe(finalize(() => {
        this.cargando = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (datos: Paciente[]) => this.pacientes = datos,
        error: () => this.error = 'Error al cargar pacientes iniciales.'
      });

    // Especialidades
    this.pacienteService
      .obtenerEspecialidades()
      .pipe(finalize(() => this.cdr.markForCheck()))
      .subscribe({
        next: (datos: Especialidad[]) => this.especialidades = datos,
        error: () => {}
      });

    // Estado import + hist general
    this.refrescarEstadoImport();
    this.cargarHistogramaGeneral();
  }

  // =========================
  // IMPORTACIÓN EXCEL
  // =========================
  refrescarEstadoImport(): void {
    this.cargandoImport = true;
    this.errorImport = null;

    this.importacionService
      .estado()
      .pipe(finalize(() => {
        this.cargandoImport = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (e) => this.estadoImport = e,
        error: () => this.errorImport = 'No se pudo consultar el estado de importación.'
      });
  }

  cargarLogImport(): void {
    this.importacionService.log().subscribe({
      next: (r) => {
        this.logImport = r.lines || [];
        this.cdr.markForCheck();
      },
      error: () => {}
    });
  }

  onSeleccionarPlanilla(ev: Event): void {
    const input = ev.target as HTMLInputElement;
    this.archivoPlanilla = input.files && input.files.length ? input.files[0] : null;
  }

  onSeleccionarHistor(ev: Event): void {
    const input = ev.target as HTMLInputElement;
    this.archivoHistor = input.files && input.files.length ? input.files[0] : null;
  }

  subirPlanilla(): void {
    if (!this.archivoPlanilla) {
      this.errorImport = 'Selecciona un archivo de PLANILLA primero.';
      return;
    }

    this.subiendoPlanilla = true;
    this.errorImport = null;
    this.mensajeImport = null;

    this.importacionService
      .subirPlanilla(this.archivoPlanilla)
      .pipe(finalize(() => {
        this.subiendoPlanilla = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (r: RespuestaImportacion) => {
          this.mensajeImport = r.mensaje || '✅ Planilla cargada.';
          this.cargarLogImport();
          this.refrescarEstadoImport();
        },
        error: (err: any) => {
          this.errorImport = err?.error?.detalle || 'Error subiendo planilla.';
        }
      });
  }

  subirHistor(): void {
    if (!this.archivoHistor) {
      this.errorImport = 'Selecciona un archivo de HISTOR primero.';
      return;
    }

    this.subiendoHistor = true;
    this.errorImport = null;
    this.mensajeImport = null;

    this.importacionService
      .subirHistor(this.archivoHistor)
      .pipe(finalize(() => {
        this.subiendoHistor = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (r: RespuestaImportacion) => {
          this.mensajeImport = r.mensaje || '✅ Histor cargado.';
          this.cargarLogImport();
          this.refrescarEstadoImport();
        },
        error: (err: any) => {
          this.errorImport = err?.error?.detalle || 'Error subiendo histor.';
        }
      });
  }

  sincronizarImportacion(): void {
    if (!this.estadoImport?.planilla_cargada || !this.estadoImport?.histor_cargada) {
      this.errorImport = 'Debes cargar PLANILLA y HISTOR antes de procesar.';
      return;
    }

    this.sincronizando = true;
    this.errorImport = null;
    this.mensajeImport = '⏳ Procesando excels... por favor espera.';
    this.logImport = [];

    this.importacionService
      .sincronizar()
      .pipe(finalize(() => {
        this.sincronizando = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (r) => {
          this.mensajeImport = r.mensaje || '✅ Sincronización terminada.';
          this.cargarLogImport();
          this.refrescarEstadoImport();

          // refrescar data
          this.cargarHistogramaGeneral();
          if (this.pacienteSeleccionado) {
            this.cargarCitas(this.pacienteSeleccionado.numero_documento);
            this.cargarHistogramaPaciente(this.pacienteSeleccionado.numero_documento);
          }
        },
        error: (err: any) => {
          this.errorImport = err?.error?.mensaje || '❌ Error procesando excels.';
          this.cargarLogImport();
        }
      });
  }

  limpiarImportacion(): void {
    this.errorImport = null;
    this.mensajeImport = null;

    this.importacionService.limpiar().subscribe({
      next: (r) => {
        this.mensajeImport = r.mensaje || '✅ Estado limpiado.';
        this.logImport = [];
        this.refrescarEstadoImport();
        this.cdr.markForCheck();
      },
      error: () => this.errorImport = 'No se pudo limpiar la importación.'
    });
  }

  // =========================
  // Helpers Histograma (para arreglar "Hasta hoy")
  // =========================
  hastaHoyEsperado(): number {
    const c: any = this.histPaciente?.cumplimiento;
    return Number(c?.esperado_base_hasta_hoy ?? c?.esperado_hasta_hoy ?? 0);
  }

  hastaHoyAsistidas(): number {
    const c: any = this.histPaciente?.cumplimiento;
    return Number(c?.asistidas_plan_hasta_hoy ?? c?.asistidas_hasta_hoy ?? 0);
  }

  hastaHoyPorcentaje(): number {
    const c: any = this.histPaciente?.cumplimiento;
    return Number(c?.porcentaje_base_hasta_hoy ?? c?.porcentaje_hasta_hoy ?? 0);
  }

  valorEsperadoMes(m: any): number {
    return Number(m?.esperado_mes ?? m?.esperado ?? 0);
  }

  valorAsistidasMes(m: any): number {
    return Number(m?.asistidas_total ?? m?.asistidas ?? 0);
  }

  valorPendienteMes(m: any): number {
    const esperadoMes = Number(m?.esperado_mes ?? m?.esperado ?? 0);
    const asistidasMes = Number(m?.asistidas_mes ?? 0); // solo del mes (sin arrastre)
    return Math.max(0, esperadoMes - asistidasMes);
  }

  valorPendientesTotal(m: any): number {
    return Number(m?.retraso_fin ?? m?.retraso ?? m?.pendientes ?? 0);
  }

  // =========================
  // HISTOGRAMA GENERAL + GRAFICOS
  // =========================
  cargarHistogramaGeneral(): void {
    this.cargandoHistGeneral = true;
    this.errorHistGeneral = null;

    this.importacionService
      .histogramaGeneral()
      .pipe(finalize(() => {
        this.cargandoHistGeneral = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (h) => {
          this.histGeneral = h;
          this.cdr.detectChanges();
          setTimeout(() => {
            this.pintarGraficoGeneralEspecialidad();
            this.pintarGraficoGeneralMes();
          }, 0);
        },
        error: () => this.errorHistGeneral = 'No se pudo cargar histograma general.'
      });
  }

  private pintarGraficoGeneralEspecialidad(): void {
    if (!this.histGeneral?.porEspecialidad || !this.canvasGeneralEsp) return;

    const labels = this.histGeneral.porEspecialidad.map(x => x.especialidad);
    const esperado = this.histGeneral.porEspecialidad.map(x => x.esperado);
    const asistidas = this.histGeneral.porEspecialidad.map(x => x.asistidas);

    if (this.grafGeneralEsp) this.grafGeneralEsp.destroy();

    this.grafGeneralEsp = new Chart(this.canvasGeneralEsp.nativeElement, {
      type: 'bar',
      data: {
        labels,
        datasets: [
          { label: 'Esperado', data: esperado },
          { label: 'Asistidas', data: asistidas }
        ]
      },
      options: {
        responsive: true,
        plugins: { legend: { position: 'top' } },
        scales: { y: { beginAtZero: true } }
      }
    });
  }

  private pintarGraficoGeneralMes(): void {
    if (!this.histGeneral?.porMesPrograma || !this.canvasGeneralMes) return;

    const labels = this.histGeneral.porMesPrograma.map(x => `Mes ${x.mes}`);
    const esperado = this.histGeneral.porMesPrograma.map(x => x.esperado);
    const asistidas = this.histGeneral.porMesPrograma.map(x => x.asistidas);

    if (this.grafGeneralMes) this.grafGeneralMes.destroy();

    this.grafGeneralMes = new Chart(this.canvasGeneralMes.nativeElement, {
      type: 'bar',
      data: {
        labels,
        datasets: [
          { label: 'Esperado', data: esperado },
          { label: 'Asistidas', data: asistidas }
        ]
      },
      options: {
        responsive: true,
        plugins: { legend: { position: 'top' } },
        scales: { y: { beginAtZero: true } }
      }
    });
  }

  // =========================
  // HISTOGRAMA PACIENTE + GRAFICO
  // =========================
  cargarHistogramaPaciente(numeroDocumento: string): void {
    this.cargandoHistPaciente = true;
    this.errorHistPaciente = null;
    this.histPaciente = null;

    this.importacionService
      .histogramaPaciente(numeroDocumento)
      .pipe(finalize(() => {
        this.cargandoHistPaciente = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (h) => {
          this.histPaciente = h;
          this.cdr.detectChanges();
          setTimeout(() => this.pintarGraficoPaciente(), 0);
        },
        error: () => {
          this.errorHistPaciente = 'No se pudo cargar el histograma del paciente.';
        }
      });
  }

  private pintarGraficoPaciente(): void {
    if (!this.histPaciente?.porMes || !this.canvasPaciente) return;

    const labels = this.histPaciente.porMes.map(x => `Mes ${x.mes}`);
    const esperado = this.histPaciente.porMes.map(x => (x as any).esperado ?? (x as any).esperado_mes ?? 0);
    const asistidas = this.histPaciente.porMes.map(x => (x as any).asistidas ?? (x as any).asistidas_total ?? 0);

    if (this.grafPaciente) this.grafPaciente.destroy();

    this.grafPaciente = new Chart(this.canvasPaciente.nativeElement, {
      type: 'bar',
      data: {
        labels,
        datasets: [
          { label: 'Esperado', data: esperado },
          { label: 'Asistidas', data: asistidas }
        ]
      },
      options: {
        responsive: true,
        plugins: { legend: { position: 'top' } },
        scales: { y: { beginAtZero: true } }
      }
    });
  }

  // =========================
  // BÚSQUEDA PACIENTES
  // =========================
  buscar(): void {
    this.error = null;
    this.cargando = true;
    this.pacientes = [];
    this.pacienteSeleccionado = null;
    this.citas = [];
    this.mensajeCita = null;
    this.errorCita = null;
    this.errorAsistencia = null;

    this.histPaciente = null;

    const valor = this.termino.trim();
    if (!valor) {
      this.cargando = false;
      this.error = 'Ingresa un valor para buscar.';
      return;
    }

    const obs$ = (this.tipoBusqueda === 'documento')
      ? this.pacienteService.buscarPorDocumento(valor)
      : this.pacienteService.buscarPorNombre(valor);

    obs$
      .pipe(finalize(() => {
        this.cargando = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (datos: Paciente[]) => this.pacientes = datos,
        error: () => this.error = 'Error al consultar pacientes.'
      });
  }

  seleccionarPaciente(paciente: Paciente): void {
    this.pacienteSeleccionado = paciente;
    this.mensajeCita = null;
    this.errorCita = null;
    this.errorAsistencia = null;

    this.formCita = {
      id_especialidad: '',
      fecha_cita: '',
      hora_cita: '',
      tipo_cita: '',
      observaciones: '',
      modalidad: ''
    };

    this.cargarCitas(paciente.numero_documento);
    this.cargarHistogramaPaciente(paciente.numero_documento);
  }

  cargarCitas(numeroDocumento: string): void {
    this.cargandoCitas = true;
    this.citas = [];

    this.pacienteService
      .obtenerCitasPaciente(numeroDocumento)
      .pipe(finalize(() => {
        this.cargandoCitas = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (datos: Cita[]) => this.citas = datos,
        error: () => {}
      });
  }

  // =========================
  // CREAR CITA
  // =========================
  guardarCita(): void {
    if (!this.pacienteSeleccionado) return;

    this.errorCita = null;
    this.mensajeCita = null;

    if (!this.formCita.id_especialidad) return void (this.errorCita = 'Debes seleccionar una especialidad.');
    if (!this.formCita.fecha_cita) return void (this.errorCita = 'Debes seleccionar una fecha de cita.');
    if (!this.formCita.modalidad) return void (this.errorCita = 'Debes seleccionar si la cita es presencial o telemedicina.');
    if (!this.formCita.hora_cita) return void (this.errorCita = 'Debes seleccionar una hora de cita.');

    const payload: NuevaCita = {
      numero_documento: this.pacienteSeleccionado.numero_documento,
      id_especialidad: Number(this.formCita.id_especialidad),
      fecha_cita: this.formCita.fecha_cita,
      hora_cita: this.formCita.hora_cita,
      modalidad: this.formCita.modalidad,
      tipo_cita: this.formCita.tipo_cita || null,
      observaciones: this.formCita.observaciones || null
    };

    this.guardandoCita = true;

    this.pacienteService
      .crearCita(payload)
      .pipe(finalize(() => {
        this.guardandoCita = false;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (nueva: Cita) => {
          this.citas.unshift(nueva);
          this.mensajeCita = 'Cita creada correctamente.';
          this.formCita.tipo_cita = '';
          this.formCita.observaciones = '';

          if (this.pacienteSeleccionado) {
            this.cargarHistogramaPaciente(this.pacienteSeleccionado.numero_documento);
          }
          this.cargarHistogramaGeneral();
        },
        error: (err: any) => {
          this.errorCita = err?.error?.error || 'Error creando la cita. Revisa los datos.';
        }
      });
  }

  onToggleAsistencia(cita: Cita, nuevoValor: boolean): void {
    this.errorAsistencia = null;
    const valorAnterior = cita.asistio === true;

    cita.asistio = nuevoValor;
    this.guardandoAsistenciaId = cita.id_cita;

    this.pacienteService
      .actualizarAsistenciaCita(cita.id_cita, nuevoValor)
      .pipe(finalize(() => {
        this.guardandoAsistenciaId = null;
        this.cdr.markForCheck();
      }))
      .subscribe({
        next: (actualizada: Cita) => {
          Object.assign(cita, actualizada);

          if (this.pacienteSeleccionado) {
            this.cargarHistogramaPaciente(this.pacienteSeleccionado.numero_documento);
          }
          this.cargarHistogramaGeneral();
        },
        error: (err: any) => {
          this.errorAsistencia =
            err?.error?.error ||
            'No se pudo actualizar la asistencia (solo se permiten cambios en las dos últimas citas).';
          cita.asistio = valorAnterior;
        }
      });
  }
}
