import { Component, ChangeDetectorRef } from '@angular/core';
import { Router } from '@angular/router';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { AuthService } from '../../services/auth';
import { PacienteService, AutorizacionVersion, CupInfo } from '../../services/paciente';
import { finalize } from 'rxjs/operators';
import { AppHeaderComponent } from '../shared/app-header/app-header';
import { JobsService } from '../../services/jobs';

@Component({
  selector: 'app-autorizaciones',
  standalone: true,
  imports: [CommonModule, FormsModule, AppHeaderComponent],
  templateUrl: './autorizaciones.html',
  styleUrls: ['./autorizaciones.css']
})
export class AutorizacionesComponent {
  titulo = 'Consulta PPL INPEC';

  // ---- Búsqueda ----
  tipoBusqueda: 'documento' | 'interno' | 'nombre' = 'documento';
  termino = '';

  pacientes: any[] = [];
  cargando = false;
  error: string | null = null;

  // ---- Autorizaciones ----
  pacienteSeleccionado: any = null;
  ipsDisponibles: any[] = [];
  autorizantes: any[] = [];
  cupsDisponibles: CupInfo[] = [];
  cupSeleccionado: CupInfo | null = null;
  buscandoCups = false;
  errorCups: string | null = null;
  verMasIps = false;
  departamentoInterno = '';
  observacionTraslado = '';
  autorizacionEditando: any | null = null;
  actualizandoEstado: Record<string, boolean> = {};

  versionesPorAutorizacion: Record<string, AutorizacionVersion[]> = {};
  versionActualPorAutorizacion: Record<string, number> = {};
  versionSeleccionada: Record<string, number> = {};
  cargandoVersiones: Record<string, boolean> = {};

  formAutorizacion = {
    id_ips: '',
    numero_documento_autorizante: '',
    fecha_autorizacion: '',
    observacion: '',
    cup_codigo: '',
    tipo_autorizacion: 'consultas_externas',
    tipo_servicio: '',
  };

  guardandoAutorizacion = false;
  mensajeAutorizacion: string | null = null;
  errorAutorizacion: string | null = null;

  autorizacionesPaciente: any[] = [];
  cargandoAutorizaciones = false;
  errorAutLista: string | null = null;

  descargandoPdf = false;

  constructor(
    private authService: AuthService,
    private pacienteService: PacienteService,
    private jobsService: JobsService,
    private router: Router,
    private cdr: ChangeDetectorRef
  ) {}

  // -------------------------
  // Búsqueda de pacientes
  // -------------------------
  buscar(): void {
    this.error = null;
    this.cargando = true;
    this.pacientes = [];
    this.pacienteSeleccionado = null;
    this.mensajeAutorizacion = null;
    this.errorAutorizacion = null;

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

    let obs$;

    if (this.tipoBusqueda === 'documento') {
      obs$ = this.pacienteService.buscarPorDocumento(valor);
    } else if (this.tipoBusqueda === 'interno') {
      obs$ = this.pacienteService.buscarPorInterno(valor);
    } else {
      obs$ = this.pacienteService.buscarPorNombre(valor);
    }

    obs$
      .pipe(
        finalize(() => {
          this.cargando = false;
          this.cdr.markForCheck();
        })
      )
      .subscribe({
        next: (data: any[]) => {
          this.pacientes = data;
        },
        error: (err) => {
          console.error(err);
          this.error = 'Error consultando pacientes.';
        },
      });
  }

  // -------------------------
  // Seleccionar paciente
  // -------------------------
  seleccionarPaciente(p: any): void {
    this.pacienteSeleccionado = p;
    this.mensajeAutorizacion = null;
    this.errorAutorizacion = null;
    this.autorizacionEditando = null;
    this.verMasIps = false;
    this.departamentoInterno = String(p?.epc_departamento || '').trim();
    this.observacionTraslado = '';

    this.formAutorizacion = {
      id_ips: '',
      numero_documento_autorizante: '',
      fecha_autorizacion: '',
      observacion: '',
      cup_codigo: '',
      tipo_autorizacion: 'consultas_externas',
      tipo_servicio: '',
    };

    this.autorizacionesPaciente = [];
    this.versionesPorAutorizacion = {};
    this.versionActualPorAutorizacion = {};
    this.versionSeleccionada = {};
    this.cargandoVersiones = {};
    this.errorAutLista = null;
    this.cupsDisponibles = [];
    this.cupSeleccionado = null;
    this.errorCups = null;

    this.cargarIps(p.interno, this.verMasIps);
    this.cargarAutorizantes();
  }

  cerrarAutorizacion(): void {
    this.pacienteSeleccionado = null;
    this.autorizacionesPaciente = [];
    this.mensajeAutorizacion = null;
    this.errorAutorizacion = null;
    this.errorAutLista = null;
    this.cupsDisponibles = [];
    this.cupSeleccionado = null;
    this.errorCups = null;
    this.verMasIps = false;
    this.departamentoInterno = '';
    this.observacionTraslado = '';
    this.autorizacionEditando = null;
    this.versionesPorAutorizacion = {};
    this.versionActualPorAutorizacion = {};
    this.versionSeleccionada = {};
    this.cargandoVersiones = {};
    this.cdr.markForCheck();
  }

  private cargarIps(interno: string, verTodas = false): void {
    this.ipsDisponibles = [];
    this.pacienteService
      .obtenerIpsPorInterno(interno, verTodas)
      .pipe(
        finalize(() => {
          this.cdr.markForCheck();
        })
      )
      .subscribe({
        next: (data: any[]) => {
          this.ipsDisponibles = data;
          if (
            this.autorizacionEditando &&
            this.formAutorizacion.id_ips &&
            !this.ipsDisponibles.some(
              (ips) => String(ips.id_ips) === String(this.formAutorizacion.id_ips)
            ) &&
            !this.verMasIps
          ) {
            this.verMasIps = true;
            this.cargarIps(interno, true);
            return;
          }
          this.onIpsChange();
        },
        error: (err) => {
          console.error(err);
          this.errorAutorizacion =
            'No se pudieron cargar las IPS para este interno.';
        },
      });
  }

  private cargarAutorizantes(): void {
    this.autorizantes = [];
    this.pacienteService
      .obtenerAutorizantes()
      .pipe(
        finalize(() => {
          this.cdr.markForCheck();
        })
      )
      .subscribe({
        next: (data: any[]) => {
          this.autorizantes = data;
        },
        error: (err) => {
          console.error(err);
          this.errorAutorizacion =
            'No se pudieron cargar las personas autorizantes.';
        },
      });
  }

  toggleVerMasIps(): void {
    if (!this.pacienteSeleccionado) {
      return;
    }
    this.verMasIps = !this.verMasIps;
    this.cargarIps(this.pacienteSeleccionado.interno, this.verMasIps);
  }

  onIpsChange(): void {
    const idSeleccionado = String(this.formAutorizacion.id_ips || '');
    const ipsSeleccionada = this.ipsDisponibles.find(
      (ips) => String(ips.id_ips) === idSeleccionado
    );

    if (!ipsSeleccionada) {
      this.observacionTraslado = '';
      return;
    }

    const deptoIps = String(ipsSeleccionada.departamento || '').trim();
    const deptoInterno = String(this.departamentoInterno || '').trim();
    const requiereTraslado =
      this.verMasIps &&
      deptoIps &&
      deptoInterno &&
      deptoIps.toLowerCase() !== deptoInterno.toLowerCase();

    this.observacionTraslado = requiereTraslado
      ? `Traslado a departamento ${deptoIps}`
      : '';
  }

  buscarCups(): void {
    const termino = String(this.formAutorizacion.cup_codigo || '').trim();
    if (!termino) {
      this.cupsDisponibles = [];
      this.cupSeleccionado = null;
      this.errorCups = 'Ingresa un código o descripción para buscar.';
      return;
    }

    this.buscandoCups = true;
    this.errorCups = null;
    this.cupSeleccionado = null;

    this.pacienteService
      .buscarCups(termino)
      .pipe(
        finalize(() => {
          this.buscandoCups = false;
          this.cdr.markForCheck();
        })
      )
      .subscribe({
        next: (data: CupInfo[]) => {
          this.cupsDisponibles = data || [];
          const match = this.cupsDisponibles.find(
            (cup) => cup.codigo === this.formAutorizacion.cup_codigo
          );
          this.cupSeleccionado = match || null;
          if (this.cupsDisponibles.length === 0) {
            this.errorCups = 'No se encontraron CUPS con ese criterio.';
          }
        },
        error: (err) => {
          console.error(err);
          this.errorCups = 'Error consultando CUPS.';
        },
      });
  }

  seleccionarCup(cup: CupInfo): void {
    if (!cup) return;
    this.formAutorizacion.cup_codigo = cup.codigo;
    this.cupSeleccionado = cup;
  }

  onCupInputChange(): void {
    this.cupSeleccionado = null;
  }

  // -------------------------
  // Guardar autorización
  // -------------------------
  onTipoAutorizacionChange(): void {
    if (
      this.formAutorizacion.tipo_autorizacion !==
      'brigadas_ambulancias_hospitalarios'
    ) {
      this.formAutorizacion.tipo_servicio = '';
    }
  }

  getTipoAutorizacionLabel(tipo: string | null | undefined): string {
    const normalizado = String(tipo || '').toLowerCase();
    if (normalizado === 'consultas_externas') {
      return 'Consultas externas';
    }
    if (normalizado === 'brigadas_ambulancias_hospitalarios') {
      return 'Brigadas/Ambulancias/Hospitalarios';
    }
    return tipo ? String(tipo) : '';
  }

  getTipoServicioLabel(tipo: string | null | undefined): string {
    const normalizado = String(tipo || '').toLowerCase();
    if (normalizado === 'brigadas') {
      return 'Brigadas';
    }
    if (normalizado === 'ambulancias') {
      return 'Ambulancias';
    }
    if (normalizado === 'hospitalarios') {
      return 'Hospitalarios';
    }
    return tipo ? String(tipo) : '';
  }

  getEstadoAutorizacionLabel(estado: string | null | undefined): string {
    const normalizado = String(estado || 'pendiente').toLowerCase();
    if (normalizado === 'autorizado') {
      return 'Autorizado';
    }
    if (normalizado === 'no_autorizado') {
      return 'No autorizado';
    }
    return 'Pendiente';
  }

  puedeDescargarPdfAutorizacion(autorizacion: any): boolean {
    if (this.isAdministrador()) {
      return true;
    }
    const estado = String(autorizacion?.estado_autorizacion || 'pendiente').toLowerCase();
    return estado === 'autorizado';
  }

  actualizarEstadoAutorizacion(
    autorizacion: any,
    estado: 'pendiente' | 'autorizado' | 'no_autorizado'
  ): void {
    if (!autorizacion || !this.isAdministrador()) {
      return;
    }

    const numero = String(autorizacion.numero_autorizacion || '');
    if (!numero) {
      return;
    }

    if (this.actualizandoEstado[numero]) {
      return;
    }

    this.actualizandoEstado[numero] = true;
    this.errorAutLista = null;
    const estadoPrevio = autorizacion.estado_autorizacion || 'pendiente';
    autorizacion.estado_autorizacion = estado;

    this.pacienteService
      .actualizarEstadoAutorizacion(numero, estado)
      .pipe(
        finalize(() => {
          this.actualizandoEstado[numero] = false;
          this.cdr.markForCheck();
        })
      )
      .subscribe({
        next: (resp) => {
          autorizacion.estado_autorizacion =
            resp?.autorizacion?.estado_autorizacion || estado;
        },
        error: (err) => {
          console.error(err);
          autorizacion.estado_autorizacion = estadoPrevio;
          this.errorAutLista =
            err?.error?.error || 'Error actualizando el estado de la autorizacion.';
        },
      });
  }

  private buildObservacionFinal(): string | undefined {
    const base = String(this.formAutorizacion.observacion || '').trim();
    const trasladoTexto = String(this.observacionTraslado || '').trim();
    const trasladoRegex = /\s*\|\s*Traslado a departamento[^|]*$/i;
    let baseSinTraslado = base;

    if (trasladoRegex.test(baseSinTraslado)) {
      baseSinTraslado = baseSinTraslado.replace(trasladoRegex, '').trim();
    }

    if (!trasladoTexto) {
      return baseSinTraslado || undefined;
    }

    const yaIncluye =
      baseSinTraslado.toLowerCase().includes(trasladoTexto.toLowerCase());
    if (yaIncluye) {
      return baseSinTraslado || undefined;
    }

    return [baseSinTraslado, trasladoTexto].filter(Boolean).join(' | ') || undefined;
  }

  private formatDateInput(value: string | null | undefined): string {
    if (!value) return '';
    return value.substring(0, 10);
  }

  iniciarEdicion(autorizacion: any): void {
    if (!autorizacion) return;

    this.autorizacionEditando = autorizacion;
    this.mensajeAutorizacion = null;
    this.errorAutorizacion = null;

    this.formAutorizacion = {
      id_ips: String(autorizacion.id_ips || ''),
      numero_documento_autorizante: String(
        autorizacion.numero_documento_autorizante || ''
      ),
      fecha_autorizacion: this.formatDateInput(autorizacion.fecha_autorizacion),
      observacion: autorizacion.observacion || '',
      cup_codigo: autorizacion.cup_codigo || '',
      tipo_autorizacion: autorizacion.tipo_autorizacion || 'consultas_externas',
      tipo_servicio: autorizacion.tipo_servicio || '',
    };
    this.cupSeleccionado = null;

    this.onTipoAutorizacionChange();
    this.onIpsChange();
    if (this.pacienteSeleccionado) {
      this.cargarIps(this.pacienteSeleccionado.interno, this.verMasIps);
    }
  }

  cancelarEdicion(): void {
    this.autorizacionEditando = null;
    this.observacionTraslado = '';
    this.cupSeleccionado = null;
    this.formAutorizacion = {
      id_ips: '',
      numero_documento_autorizante: '',
      fecha_autorizacion: '',
      observacion: '',
      cup_codigo: '',
      tipo_autorizacion: 'consultas_externas',
      tipo_servicio: '',
    };
  }

  guardarAutorizacion(): void {
    if (!this.pacienteSeleccionado) {
      return;
    }

    this.errorAutorizacion = null;
    this.mensajeAutorizacion = null;

    if (!this.formAutorizacion.id_ips) {
      this.errorAutorizacion = 'Debe seleccionar una IPS.';
      return;
    }
    if (!this.formAutorizacion.numero_documento_autorizante) {
      this.errorAutorizacion = 'Debe seleccionar quién autoriza.';
      return;
    }
    if (!this.formAutorizacion.cup_codigo) {
      this.errorAutorizacion = 'Debe seleccionar un CUPS.';
      return;
    }
    const tipoAutorizacion = String(
      this.formAutorizacion.tipo_autorizacion || 'consultas_externas'
    ).toLowerCase();
    const requiereServicio =
      tipoAutorizacion === 'brigadas_ambulancias_hospitalarios';
    const tipoServicio = String(
      this.formAutorizacion.tipo_servicio || ''
    ).trim().toLowerCase();

    if (requiereServicio && !tipoServicio) {
      this.errorAutorizacion = 'Debe seleccionar un tipo de servicio.';
      return;
    }

    const payload = {
      interno: this.pacienteSeleccionado.interno,
      id_ips: Number(this.formAutorizacion.id_ips),
      numero_documento_autorizante: Number(
        this.formAutorizacion.numero_documento_autorizante
      ),
      observacion: this.buildObservacionFinal(),
      fecha_autorizacion:
        this.formAutorizacion.fecha_autorizacion || undefined,
      cup_codigo: this.formAutorizacion.cup_codigo,
      tipo_autorizacion: tipoAutorizacion,
      tipo_servicio: requiereServicio ? tipoServicio : undefined,
    };

    this.guardandoAutorizacion = true;

    const request$ = this.autorizacionEditando
      ? this.pacienteService.actualizarAutorizacion(
          this.autorizacionEditando.numero_autorizacion,
          payload
        )
      : this.pacienteService.crearAutorizacion(payload);

    request$
      .pipe(
        finalize(() => {
          this.guardandoAutorizacion = false;
          this.cdr.markForCheck();
        })
      )
      .subscribe({
        next: (resp: any) => {
          if (this.autorizacionEditando) {
            const versionTexto = resp?.version ? ` (v${resp.version})` : '';
            this.mensajeAutorizacion = `Autorizacion ${resp.numero_autorizacion} actualizada${versionTexto}.`;
            this.autorizacionEditando = null;
            this.verAutorizaciones();
          } else {
            this.mensajeAutorizacion = `Autorizacion N ${resp.numero_autorizacion} creada el ${resp.fecha_autorizacion}.`;
          }
        },
        error: (err) => {
          console.error(err);
          this.errorAutorizacion =
            err.error?.error || 'Error guardando la autorizacion.';
        },
      });
  }

  cargarVersiones(numeroAutorizacion: string): void {
    if (this.cargandoVersiones[numeroAutorizacion]) {
      return;
    }

    this.cargandoVersiones[numeroAutorizacion] = true;

    this.pacienteService.obtenerVersionesAutorizacion(numeroAutorizacion).subscribe({
      next: (resp) => {
        const versiones = resp?.versiones || [];
        const versionActual = resp?.version_actual || 1;

        this.versionesPorAutorizacion[numeroAutorizacion] = versiones;
        this.versionActualPorAutorizacion[numeroAutorizacion] = versionActual;
        this.versionSeleccionada[numeroAutorizacion] =
          this.versionSeleccionada[numeroAutorizacion] || versionActual;
        this.cargandoVersiones[numeroAutorizacion] = false;
        this.cdr.markForCheck();
      },
      error: (err) => {
        console.error(err);
        this.cargandoVersiones[numeroAutorizacion] = false;
        this.cdr.markForCheck();
      },
    });
  }

  getVersionSeleccionada(numeroAutorizacion: string, fallback?: number | null): number | null {
    const seleccion = this.versionSeleccionada[numeroAutorizacion];
    if (typeof seleccion === 'number') {
      return seleccion;
    }
    if (typeof fallback === 'number') {
      return fallback;
    }
    return null;
  }

  // -------------------------
  // Ver autorizaciones del interno
  // -------------------------
  verAutorizaciones(): void {
    if (!this.pacienteSeleccionado) return;

    this.cargandoAutorizaciones = true;
    this.errorAutLista = null;
    this.autorizacionesPaciente = [];
    this.versionesPorAutorizacion = {};
    this.versionActualPorAutorizacion = {};
    this.versionSeleccionada = {};
    this.cargandoVersiones = {};

    this.pacienteService
      .obtenerAutorizacionesPorInterno(this.pacienteSeleccionado.interno)
      .pipe(
        finalize(() => {
          this.cargandoAutorizaciones = false;
          this.cdr.markForCheck();
        })
      )
      .subscribe({
        next: (data: any[]) => {
          this.autorizacionesPaciente = data;
        },
        error: (err) => {
          console.error(err);
          this.errorAutLista = 'Error consultando autorizaciones.';
        },
      });
  }

  // -------------------------
  // Descargar PDF
  // -------------------------
  descargarPdf(autorizacion: any, version?: number | null): void {
    if (!autorizacion) {
      return;
    }

    if (!this.puedeDescargarPdfAutorizacion(autorizacion)) {
      this.errorAutLista = 'Autorizacion pendiente o no autorizada.';
      return;
    }

    const numeroAutorizacion = autorizacion.numero_autorizacion;
    this.descargandoPdf = true;
    this.errorAutLista = null;

    const versionNum = typeof version === 'number' ? version : undefined;
    this.authService.crearJobPdfAutorizacion(numeroAutorizacion, versionNum).subscribe({
      next: (job) => {
        this.jobsService.pollJob(job.id).subscribe({
          next: (estado) => {
            if (estado.status === 'completed') {
              const fileName =
                estado.result?.fileName || `autorizacion_${numeroAutorizacion}.pdf`;

              this.jobsService.downloadJobFile(job.id).subscribe({
                next: (data) => {
                  const blob = new Blob([data], { type: 'application/pdf' });
                  const url = window.URL.createObjectURL(blob);

                  const a = document.createElement('a');
                  a.href = url;
                  a.download = fileName;
                  document.body.appendChild(a);
                  a.click();
                  document.body.removeChild(a);
                  window.URL.revokeObjectURL(url);

                  this.descargandoPdf = false;
                  this.cdr.markForCheck();
                },
                error: (error) => {
                  console.error('Error descargando PDF:', error);
                  this.errorAutLista =
                    'Error descargando el PDF de la autorizaci?n.';
                  this.descargandoPdf = false;
                  this.cdr.markForCheck();
                }
              });
            }

            if (estado.status === 'failed') {
              this.errorAutLista =
                estado.error?.message ||
                'Error generando el PDF de la autorizaci?n.';
              this.descargandoPdf = false;
              this.cdr.markForCheck();
            }
          },
          error: (error) => {
            console.error(error);
            this.errorAutLista = 'Error consultando el estado del PDF.';
            this.descargandoPdf = false;
            this.cdr.markForCheck();
          }
        });
      },
      error: (error) => {
        console.error(error);
        this.errorAutLista = 'Error solicitando la generaci?n del PDF.';
        this.descargandoPdf = false;
        this.cdr.markForCheck();
      }
    });
  }

  irAAutorizacionesPorFecha(): void {
    this.router.navigate(['/autorizaciones-por-fecha']);
  }

  irACargarPacientes(): void {
    this.router.navigate(['/cargar-pacientes']);
  }

  irADashboard(): void {
    this.router.navigate(['/dashboard']);
  }

  // ---- Métodos de autenticación ----
  logout(): void {
    this.authService.logout();
  }

  isLoggedIn(): boolean {
    return this.authService.isLoggedIn();
  }

  getCurrentUser(): any {
    return this.authService.getCurrentUser();
  }

  // Métodos para verificar permisos
  puedeCargarPacientes(): boolean {
    return this.authService.puedeCargarPacientes();
  }

  puedeDescargarPdfs(): boolean {
    return this.authService.puedeDescargarPdfs();
  }

  puedeVerTodasAutorizaciones(): boolean {
    return this.authService.puedeVerTodasAutorizaciones();
  }

  puedeGenerarAutorizaciones(): boolean {
    return this.authService.puedeGenerarAutorizaciones();
  }

  isAdministrador(): boolean {
    return this.authService.isAdministrador();
  }

  isAdministrativoSede(): boolean {
    return this.authService.isAdministrativoSede();
  }

  tieneAccesoAEstablecimiento(codigoEstablecimiento: string): boolean {
    return this.authService.tieneAccesoAEstablecimiento(codigoEstablecimiento);
  }
}
