import { Controller, Get, Post, Patch, Param, Query, Body, Req, Logger } from '@nestjs/common';
import { Request } from 'express';
import { GraphService } from './graph.service';

interface JwtUser {
  sub: string;
  email: string;
  tenantId: string;
}

/**
 * Office365Controller — Globale Microsoft 365 Übersicht
 *
 * Zeigt alle M365-Daten des eingeloggten Users (ohne Kontakt-Filter).
 *
 * Routen:
 * GET /crm/office365/emails                          — Alle E-Mails (Posteingang)
 * GET /crm/office365/calendar                        — Alle Kalendertermine (nächste 30 Tage)
 * GET /crm/office365/contacts                        — Alle Outlook-Kontakte
 * GET /crm/office365/tasks                           — Alle Aufgaben (Microsoft To Do)
 * GET /crm/office365/folders                         — Alle Mail-Ordner
 * GET /crm/office365/folders/:folderId/messages      — E-Mails in einem Ordner (mit ?days=7)
 */
@Controller('office365')
export class Office365Controller {
  private readonly logger = new Logger(Office365Controller.name);

  constructor(private readonly graphService: GraphService) {}

  @Get('emails')
  async getEmails(@Req() req: Request & { user: JwtUser }) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const emails = await this.graphService.getAllEmails(jwt, req.user.sub);
    return { success: true, data: emails, meta: { count: emails.length } };
  }

  @Get('calendar/range')
  async getCalendarRange(
    @Req() req: Request & { user: JwtUser },
    @Query('startDate') startDate: string,
    @Query('endDate') endDate: string,
  ) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const events = await this.graphService.getCalendarEventsForRange(
      jwt,
      req.user.sub,
      startDate,
      endDate,
    );
    return { success: true, data: events, meta: { count: events.length } };
  }

  @Get('calendar')
  async getCalendar(@Req() req: Request & { user: JwtUser }) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const events = await this.graphService.getAllCalendarEvents(jwt, req.user.sub);
    return { success: true, data: events, meta: { count: events.length } };
  }

  @Get('contacts')
  async getContacts(@Req() req: Request & { user: JwtUser }) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const contacts = await this.graphService.getAllOutlookContacts(jwt, req.user.sub);
    return { success: true, data: contacts, meta: { count: contacts.length } };
  }

  @Get('tasks')
  async getTasks(@Req() req: Request & { user: JwtUser }) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const taskLists = await this.graphService.getTasks(jwt, req.user.sub);
    const totalTasks = taskLists.reduce((sum, l) => sum + l.tasks.length, 0);
    return {
      success: true,
      data: taskLists,
      meta: { listCount: taskLists.length, taskCount: totalTasks },
    };
  }

  /** Alle offenen Aufgaben flach (inkl. Body für CRM-Sync-Erkennung) */
  @Get('tasks/flat')
  async getTasksFlat(@Req() req: Request & { user: JwtUser }) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const tasks = await this.graphService.getAllTasksFlat(jwt, req.user.sub);
    return { success: true, data: tasks, meta: { count: tasks.length } };
  }

  /** Neue Aufgabe in M365 erstellen (z.B. CRM-Aufgabe übernehmen) */
  @Post('tasks')
  async createTask(
    @Req() req: Request & { user: JwtUser },
    @Body() body: { title: string; bodyContent?: string; dueDateISO?: string },
  ) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const result = await this.graphService.createM365Task(
      jwt,
      body.title,
      body.bodyContent,
      body.dueDateISO,
    );
    return { success: true, data: result };
  }

  /** Aufgabe als erledigt markieren */
  @Patch('tasks/:listId/:taskId/complete')
  async completeTask(
    @Req() req: Request & { user: JwtUser },
    @Param('listId') listId: string,
    @Param('taskId') taskId: string,
  ) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    await this.graphService.completeM365Task(jwt, listId, taskId);
    return { success: true };
  }

  /** Microsoft-365-Benutzerprofil abrufen (für Profilanreicherung) */
  @Get('profile')
  async getProfile(@Req() req: Request & { user: JwtUser }) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const profile = await this.graphService.getM365Profile(jwt);
    return { success: true, data: profile };
  }

  /** Microsoft-365-Profilbild abrufen (96x96 JPEG als Base64 Data-URL) */
  @Get('photo')
  async getPhoto(@Req() req: Request & { user: JwtUser }) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const photoBase64 = await this.graphService.getM365Photo(jwt);
    return { success: true, data: { photoBase64 } };
  }

  @Get('folders')
  async getMailFolders(@Req() req: Request & { user: JwtUser }) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const folders = await this.graphService.getMailFolders(jwt, req.user.sub);
    return { success: true, data: folders, meta: { count: folders.length } };
  }

  @Get('folders/:folderId/messages')
  async getMailsInFolder(
    @Req() req: Request & { user: JwtUser },
    @Param('folderId') folderId: string,
    @Query('days') days?: string,
  ) {
    const jwt = (req.headers.authorization ?? '').replace('Bearer ', '');
    const daysNum = days ? parseInt(days, 10) : 7;
    const emails = await this.graphService.getMailsByFolder(
      jwt,
      req.user.sub,
      folderId,
      isNaN(daysNum) ? 7 : daysNum,
    );
    return { success: true, data: emails, meta: { count: emails.length } };
  }
}
