import { Hono } from "hono";
import { createKV } from "../lib/create-kv.js";
import { assertOwner } from "../lib/auth.js";

// Types für Buchungen (vereinfacht für CalDAV)
type Booking = {
  id: string;
  treatments?: Array<{id: string, name: string, duration: number, price: number}>;
  customerName: string;
  customerEmail?: string;
  customerPhone?: string;
  appointmentDate: string; // YYYY-MM-DD
  appointmentTime: string; // HH:MM
  status: "pending" | "confirmed" | "cancelled" | "completed";
  notes?: string;
  // Deprecated fields for backward compatibility
  treatmentId?: string;
  bookedDurationMinutes?: number;
  createdAt: string;
};

type Treatment = {
  id: string;
  name: string;
  description: string;
  price: number;
  duration: number;
  category: string;
  createdAt: string;
};

// KV-Stores
const bookingsKV = createKV<Booking>("bookings");
const treatmentsKV = createKV<Treatment>("treatments");
const sessionsKV = createKV<any>("sessions");

export const caldavApp = new Hono();

// Helper-Funktionen für ICS-Format
function formatDateTime(dateStr: string, timeStr: string): string {
  // Konvertiere YYYY-MM-DD HH:MM zu UTC-Format für ICS
  const [year, month, day] = dateStr.split('-').map(Number);
  const [hours, minutes] = timeStr.split(':').map(Number);
  
  const date = new Date(year, month - 1, day, hours, minutes);
  return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
}

function addMinutesToTime(timeStr: string, minutesToAdd: number): string {
  const [hours, minutes] = timeStr.split(':').map(Number);
  const totalMinutes = hours * 60 + minutes + minutesToAdd;
  const newHours = Math.floor(totalMinutes / 60);
  const newMinutes = totalMinutes % 60;
  return `${String(newHours).padStart(2, '0')}:${String(newMinutes).padStart(2, '0')}`;
}

function generateICSContent(bookings: Booking[], treatments: Treatment[]): string {
  const now = new Date().toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
  
  let ics = `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Stargirlnails//Booking Calendar//DE
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:Stargirlnails Termine
X-WR-CALDESC:Terminkalender für Stargirlnails
X-WR-TIMEZONE:Europe/Berlin
`;

  // Nur bestätigte und ausstehende Termine in den Kalender aufnehmen
  const activeBookings = bookings.filter(b => 
    b.status === 'confirmed' || b.status === 'pending'
  );

  for (const booking of activeBookings) {
    // Handle new treatments array structure
    let treatmentNames: string;
    let duration: number;
    let treatmentDetails: string;
    let totalPrice = 0;

    if (booking.treatments && Array.isArray(booking.treatments) && booking.treatments.length > 0) {
      // Use new treatments array
      treatmentNames = booking.treatments.map(t => t.name).join(', ');
      
      duration = booking.treatments.reduce((sum, t) => sum + (t.duration || 0), 0);
      totalPrice = booking.treatments.reduce((sum, t) => sum + ((t.price || 0) / 100), 0);
      
      // Build detailed treatment list for description
      treatmentDetails = booking.treatments
        .map(t => `- ${t.name} (${t.duration} Min., ${(t.price / 100).toFixed(2)}€)`)
        .join('\\n');
      
      if (booking.treatments.length > 1) {
        treatmentDetails += `\\n\\nGesamt: ${duration} Min., ${totalPrice.toFixed(2)}€`;
      }
    } else {
      // Fallback to deprecated treatmentId for backward compatibility
      const treatment = booking.treatmentId ? treatments.find(t => t.id === booking.treatmentId) : null;
      treatmentNames = treatment?.name || 'Unbekannte Behandlung';
      duration = booking.bookedDurationMinutes || treatment?.duration || 60;
      treatmentDetails = `Behandlung: ${treatmentNames}`;
      if (treatment?.price) {
        treatmentDetails += ` (${duration} Min., ${(treatment.price / 100).toFixed(2)}€)`;
      }
    }
    
    const startTime = formatDateTime(booking.appointmentDate, booking.appointmentTime);
    const endTimeStr = addMinutesToTime(booking.appointmentTime, duration);
    const endTime = formatDateTime(booking.appointmentDate, endTimeStr);

    // UID für jeden Termin (eindeutig)
    const uid = `booking-${booking.id}@stargirlnails.de`;
    
    // Status für ICS
    const status = booking.status === 'confirmed' ? 'CONFIRMED' : 'TENTATIVE';
    
    ics += `BEGIN:VEVENT
UID:${uid}
DTSTAMP:${now}
DTSTART:${startTime}
DTEND:${endTime}
SUMMARY:${treatmentNames} - ${booking.customerName}
DESCRIPTION:${treatmentDetails}\\n\\nKunde: ${booking.customerName}${booking.customerPhone ? `\\nTelefon: ${booking.customerPhone}` : ''}${booking.notes ? `\\nNotizen: ${booking.notes}` : ''}
STATUS:${status}
TRANSP:OPAQUE
END:VEVENT
`;
  }

  ics += `END:VCALENDAR`;
  
  return ics;
}

// CalDAV Discovery (PROPFIND auf Root)
caldavApp.all("/", async (c) => {
  if (c.req.method !== 'PROPFIND') {
    return c.text('Method Not Allowed', 405);
  }
  const response = `<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:response>
    <D:href>/caldav/</D:href>
    <D:propstat>
      <D:prop>
        <D:displayname>Stargirlnails Terminkalender</D:displayname>
        <C:calendar-description>Termine für Stargirlnails</C:calendar-description>
        <C:supported-calendar-component-set>
          <C:comp name="VEVENT"/>
        </C:supported-calendar-component-set>
        <C:calendar-timezone>Europe/Berlin</C:calendar-timezone>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>`;

  return c.text(response, 207, {
    "Content-Type": "application/xml; charset=utf-8",
    "DAV": "1, 3, calendar-access, calendar-schedule",
  });
});

// Calendar Collection PROPFIND
caldavApp.all("/calendar/", async (c) => {
  if (c.req.method !== 'PROPFIND') {
    return c.text('Method Not Allowed', 405);
  }
  const response = `<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CS="http://calendarserver.org/ns/">
  <D:response>
    <D:href>/caldav/calendar/</D:href>
    <D:propstat>
      <D:prop>
        <D:displayname>Stargirlnails Termine</D:displayname>
        <C:calendar-description>Alle Termine von Stargirlnails</C:calendar-description>
        <C:supported-calendar-component-set>
          <C:comp name="VEVENT"/>
        </C:supported-calendar-component-set>
        <C:calendar-timezone>Europe/Berlin</C:calendar-timezone>
        <CS:getctag>${Date.now()}</CS:getctag>
        <D:sync-token>${Date.now()}</D:sync-token>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>`;

  return c.text(response, 207, {
    "Content-Type": "application/xml; charset=utf-8",
  });
});

// Calendar Events PROPFIND
caldavApp.all("/calendar/events.ics", async (c) => {
  if (c.req.method !== 'PROPFIND') {
    return c.text('Method Not Allowed', 405);
  }
  const response = `<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns:CS="http://calendarserver.org/ns/">
  <D:response>
    <D:href>/caldav/calendar/events.ics</D:href>
    <D:propstat>
      <D:prop>
        <D:getcontenttype>text/calendar; charset=utf-8</D:getcontenttype>
        <D:getetag>"${Date.now()}"</D:getetag>
        <D:displayname>Stargirlnails Termine</D:displayname>
        <C:calendar-data>BEGIN:VCALENDAR\\nVERSION:2.0\\nEND:VCALENDAR</C:calendar-data>
      </D:prop>
      <D:status>HTTP/1.1 200 OK</D:status>
    </D:propstat>
  </D:response>
</D:multistatus>`;

  return c.text(response, 207, {
    "Content-Type": "application/xml; charset=utf-8",
  });
});

// GET Calendar Data (ICS-Datei)
caldavApp.get("/calendar/events.ics", async (c) => {
  try {
    // Authentifizierung über Token im Query-Parameter
    const token = c.req.query('token');
    if (!token) {
      return c.text('Unauthorized - Token required', 401);
    }

    // Token validieren
    const tokenData = await sessionsKV.getItem(token);
    if (!tokenData) {
      return c.text('Unauthorized - Invalid token', 401);
    }
    
    // Prüfe, ob es ein CalDAV-Token ist (durch Ablaufzeit und fehlende type-Eigenschaft erkennbar)
    // CalDAV-Tokens haben eine kürzere Ablaufzeit (24h) als normale Sessions
    const tokenAge = Date.now() - new Date(tokenData.createdAt).getTime();
    if (tokenAge > 24 * 60 * 60 * 1000) { // 24 Stunden
      return c.text('Unauthorized - Token expired', 401);
    }

    // Token-Ablaufzeit prüfen
    if (new Date(tokenData.expiresAt) < new Date()) {
      return c.text('Unauthorized - Token expired', 401);
    }

    const bookings = await bookingsKV.getAllItems();
    const treatments = await treatmentsKV.getAllItems();
    
    const icsContent = generateICSContent(bookings, treatments);
    
    return c.text(icsContent, 200, {
      "Content-Type": "text/calendar; charset=utf-8",
      "Content-Disposition": "inline; filename=\"stargirlnails-termine.ics\"",
      "Cache-Control": "no-cache, no-store, must-revalidate",
      "Pragma": "no-cache",
      "Expires": "0",
    });
  } catch (error) {
    console.error("CalDAV GET error:", error);
    return c.text('Internal Server Error', 500);
  }
});

// Fallback für andere CalDAV-Requests
caldavApp.all("*", async (c) => {
  console.log(`CalDAV: Unhandled ${c.req.method} request to ${c.req.url}`);
  return c.text('Not Found', 404);
});
