import { Logger } from '@jig-software/logger';
import { Controller, Inject } from '@jig-software/sdk';
import ExcelJS from 'exceljs';
import path from 'path';
import { readingReportContract } from '../shared';
import { createFileOutput } from '@jig-software/trest-core';
import fs from 'fs';

interface ReadingStats {
  min?: string;
  max?: string;
  avg?: string;
}

interface DeviceData {
  building: string;
  floor: string;
  device_name: string;
  min_max_avg: Record<string, ReadingStats>;
  readings: Record<string, Record<string, string>>;
}

interface EventData {
  building: string;
  floor: string;
  device_name: string;
  event_time: string;
  event_type: string;
  temperature: string;
  humidity: string;
  battery: string;
}

interface ReportParams {
  start_date?: string;
  end_date?: string;
  time_step?: string;
}

export class ReadingReportController extends Controller {
  @Inject()
  protected logger!: Logger;

  constructor() {
    super();
    this.logger.setTag(this.constructor.name);
    this.implement(readingReportContract, (r) =>
      r.handlers({
        generateReadingsReport: {
          handler: async (FullReportSchema) => {
            const data: DeviceData[] = FullReportSchema.data;
            const reportParams: ReportParams = FullReportSchema.report_params;
            const workbook = new ExcelJS.Workbook();
            const worksheet = workbook.addWorksheet('Reading Records');

            // ---------------- Logos ----------------
            const jecLogoId = workbook.addImage({
              filename: path.resolve('asset/jec_logo.jpg'),
              extension: 'jpeg',
            });

            const fastLogoId = workbook.addImage({
              filename: path.resolve('asset/fast_logo.jpg'),
              extension: 'jpeg',
            });

            worksheet.addImage(jecLogoId, {
              tl: { col: 0, row: 0 },
              ext: { width: 120, height: 120 },
            });
            worksheet.addImage(fastLogoId, {
              tl: { col: 7, row: 0 },
              ext: { width: 120, height: 60 },
            });

            // ---------------- Title ----------------
            worksheet.mergeCells('B1:G2');
            const titleCell = worksheet.getCell('B1');
            titleCell.value = 'Reading Report';
            titleCell.alignment = { horizontal: 'center', vertical: 'middle' };
            titleCell.font = { bold: true, size: 18 };

            // ---------------- Fixed params ----------------
            const fixedParams = [
              ['Start Date:', reportParams.start_date ?? ''],
              ['End Date:', reportParams.end_date ?? ''],
              ['Time Step:', reportParams.time_step ?? ''],
            ];

            fixedParams.forEach(([label, value], idx) => {
              worksheet.getCell(4 + idx, 2).value = label;
              worksheet.getCell(4 + idx, 3).value = value;
            });

            // ---------------- Headers ----------------
            const allDates = Array.from(
              new Set(
                data.flatMap((device) =>
                  Object.values(device.readings).flatMap((r) => Object.keys(r)),
                ),
              ),
            ).sort();

            const headers = [
              'Building',
              'Floor',
              'Device Name',
              'Reading Type',
              'Minimum',
              'Maximum',
              'Average',
              ...allDates,
            ];

            const headerRowIndex = 7;
            const headerRow = worksheet.getRow(headerRowIndex);
            headerRow.values = headers;
            headerRow.eachCell((cell) => {
              cell.font = { bold: true };
              cell.fill = {
                type: 'pattern',
                pattern: 'solid',
                fgColor: { argb: 'FFD9D9D9' },
              };
            });

            // ---------------- Data ----------------
            let currentRow = headerRowIndex + 1;

            for (const device of data) {
              const types = Object.keys(device.readings);
              const startRow = currentRow;
              const endRow = currentRow + types.length - 1;

              if (types.length > 1) {
                worksheet.mergeCells(startRow, 1, endRow, 1);
                worksheet.mergeCells(startRow, 2, endRow, 2);
                worksheet.mergeCells(startRow, 3, endRow, 3);
              }

              worksheet.getCell(startRow, 1).value = device.building;
              worksheet.getCell(startRow, 2).value = device.floor;
              worksheet.getCell(startRow, 3).value = device.device_name;

              for (const type of types) {
                const row = worksheet.getRow(currentRow);
                if (type == 'Temperature') {
                  row.getCell(4).value = 'Temperature (°C)';
                } else if (type == 'Humidity') {
                  row.getCell(4).value = 'Humidity (%)';
                } else if (type == 'Battery') {
                  row.getCell(4).value = 'Battery (%)';
                }

                const stats = device.min_max_avg?.[type] ?? {};
                row.getCell(5).value = stats.min ?? '-';
                row.getCell(6).value = stats.max ?? '-';
                row.getCell(7).value = stats.avg ?? '-';

                allDates.forEach((date, idx) => {
                  row.getCell(8 + idx).value =
                    device.readings[type]?.[date] ?? '-';
                });

                currentRow++;
              }

              console.log(
                `Processed device '${device.device_name}' rows ${startRow}–${endRow}`,
              );
            }

            // ---------------- Auto-width ----------------
            worksheet.columns.forEach((col) => {
              let max = 10;
              col.eachCell!({ includeEmpty: true }, (cell) => {
                const len = String(cell.value ?? '').length;
                max = Math.max(max, len);
              });
              col.width = max + 2;
            });

            // worksheet.autoFilter = {
            //   from: { row: headerRowIndex, column: 1 },
            //   to: { row: currentRow - 1, column: headers.length },
            // };

            // ---------------- Save file ----------------
            const outputPath = path.resolve('event_report.xlsx');
            await workbook.xlsx.writeFile(outputPath);
            console.log(`Excel report generated: ${outputPath}`);
            const readStream = fs.createReadStream(outputPath);

            return createFileOutput(readStream, 'event_report.xlsx');
          },
        },
        generateEventsReport: {
          handler: async (FullEventSchema) => {
            const { data, report_params } = FullEventSchema;

            const workbook = new ExcelJS.Workbook();
            const worksheet = workbook.addWorksheet('Event Records');

            // ---------------- Logos ----------------
            const jecLogoId = workbook.addImage({
              filename: path.resolve('asset/jec_logo.jpg'),
              extension: 'jpeg',
            });
            const fastLogoId = workbook.addImage({
              filename: path.resolve('asset/fast_logo.jpg'),
              extension: 'jpeg',
            });

            worksheet.addImage(jecLogoId, {
              tl: { col: 0, row: 0 },
              ext: { width: 120, height: 120 },
            });
            worksheet.addImage(fastLogoId, {
              tl: { col: 7, row: 0 },
              ext: { width: 120, height: 60 },
            });

            // ---------------- Title ----------------
            worksheet.mergeCells('B1:G2');
            const titleCell = worksheet.getCell('B1');
            titleCell.value = 'Event Report';
            titleCell.alignment = { horizontal: 'center', vertical: 'middle' };
            titleCell.font = { bold: true, size: 18 };

            // ---------------- Fixed params ----------------
            worksheet.getCell(4, 2).value = 'Start Date:';
            worksheet.getCell(4, 3).value = report_params.start_date;
            worksheet.getCell(5, 2).value = 'End Date:';
            worksheet.getCell(5, 3).value = report_params.end_date;

            // ---------------- Headers ----------------
            const headers = [
              'Building',
              'Floor',
              'Device Name',
              'Event Time',
              'Event Type',
              'Temperature',
              'Humidity',
              'Battery',
            ];

            const headerRowIndex = 7;
            const headerRow = worksheet.getRow(headerRowIndex);
            headerRow.values = headers;
            headerRow.eachCell((cell) => {
              cell.font = { bold: true };
              cell.fill = {
                type: 'pattern',
                pattern: 'solid',
                fgColor: { argb: 'FFD9D9D9' },
              };
            });

            // ---------------- Data ----------------
            let currentRow = headerRowIndex + 1;

            data.forEach((event) => {
              const row = worksheet.getRow(currentRow);
              row.getCell(1).value = event.building;
              row.getCell(2).value = event.floor;
              row.getCell(3).value = event.device_name;
              row.getCell(4).value = event.event_time;
              row.getCell(5).value = event.event_type;
              row.getCell(6).value = event.temperature;
              row.getCell(7).value = event.humidity;
              row.getCell(8).value = event.battery;

              currentRow++;
            });

            // ---------------- Auto-width ----------------
            worksheet.columns.forEach((col) => {
              let max = 10;
              col.eachCell!({ includeEmpty: true }, (cell) => {
                const len = String(cell.value ?? '').length;
                max = Math.max(max, len);
              });
              col.width = max + 2;
            });

            // ---------------- Save file ----------------
            const outputPath = path.resolve('event_report.xlsx');
            await workbook.xlsx.writeFile(outputPath);
            console.log(`Excel report generated: ${outputPath}`);

            // ---------------- Return as stream ----------------
            const readStream = fs.createReadStream(outputPath);
            return createFileOutput(readStream, 'event_report.xlsx'); // your helper
          },
        },
      }),
    );
  }
}
