export const dynamic = 'force-dynamic'
import { NextResponse } from 'next/server'
import { google } from 'googleapis'
import * as fs from 'fs'
import * as path from 'path'

function nextDayISO(date: string): string {
  const d = new Date(`${date}T00:00:00Z`)
  d.setUTCDate(d.getUTCDate() + 1)
  return d.toISOString().slice(0, 10)
}

function getAuth(readonly = true) {
  const scopes = readonly
    ? ['https://www.googleapis.com/auth/calendar.readonly']
    : ['https://www.googleapis.com/auth/calendar']

  // 1) Предпочтительно — base64. docker --env-file не парсит кавычки и не
  //    поддерживает многострочные значения, а private_key в JSON ломается
  //    на переводах строк → base64 это решает (одна строка ASCII).
  const saB64 = process.env.GOOGLE_SA_JSON_B64
  if (saB64) {
    try {
      const sa = JSON.parse(Buffer.from(saB64, 'base64').toString('utf-8'))
      return new google.auth.GoogleAuth({ credentials: sa, scopes })
    } catch (e) {
      console.error('[calendar] GOOGLE_SA_JSON_B64 decode failed:', e)
    }
  }
  // 2) Сырая JSON-строка (legacy).
  const saJson = process.env.GOOGLE_SA_JSON
  if (saJson) {
    try {
      const sa = JSON.parse(saJson)
      return new google.auth.GoogleAuth({ credentials: sa, scopes })
    } catch (e) {
      console.error('[calendar] GOOGLE_SA_JSON parse failed:', e)
    }
  }
  // 3) Fallback на файл (для локальной разработки).
  const saPath = path.join(process.cwd(), 'google-sa.json')
  if (fs.existsSync(saPath)) {
    return new google.auth.GoogleAuth({ keyFile: saPath, scopes })
  }
  return null
}

export async function GET(req: Request) {
  const { searchParams } = new URL(req.url)
  const range = searchParams.get('range') || 'today'

  const auth = getAuth(true)
  if (!auth) {
    return NextResponse.json({ events: [], error: 'not_configured' })
  }

  const daniilCalendarId = process.env.DANIIL_CALENDAR_ID || 'daniilklimov25@gmail.com'
  const svetaCalendarId = process.env.SVETA_CALENDAR_ID || ''

  const now = new Date()
  let timeMin: string
  let timeMax: string

  // Moscow boundaries (UTC+3, no DST). 00:00 MSK = 21:00 UTC previous day.
  const MSK_OFFSET_MS = 3 * 3600 * 1000
  const mskNow = new Date(now.getTime() + MSK_OFFSET_MS)
  const my = mskNow.getUTCFullYear()
  const mm = mskNow.getUTCMonth()
  const md = mskNow.getUTCDate()
  const mskMidnight = (y: number, m: number, d: number) =>
    new Date(Date.UTC(y, m, d) - MSK_OFFSET_MS).toISOString()

  if (range === 'today') {
    timeMin = mskMidnight(my, mm, md)
    timeMax = mskMidnight(my, mm, md + 1)
  } else if (range === 'week') {
    timeMin = mskMidnight(my, mm, md)
    timeMax = mskMidnight(my, mm, md + 7)
  } else {
    // month — support year/month query params
    const targetYear = parseInt(searchParams.get('year') || String(now.getFullYear()))
    const targetMonth = parseInt(searchParams.get('month') || String(now.getMonth()))
    timeMin = new Date(targetYear, targetMonth, 1).toISOString()
    timeMax = new Date(targetYear, targetMonth + 1, 0, 23, 59).toISOString()
  }

  const calendarClient = google.calendar({ version: 'v3', auth: auth as any })

  const calendars = [
    { id: daniilCalendarId, owner: 'daniil', color: '#6366f1', name: 'Даниил' },
    ...(svetaCalendarId ? [{ id: svetaCalendarId, owner: 'sveta', color: '#ec4899', name: 'Света' }] : [])
  ]

  const results = await Promise.allSettled(
    calendars.map(cal =>
      calendarClient.events.list({
        calendarId: cal.id,
        timeMin,
        timeMax,
        singleEvents: true,
        orderBy: 'startTime',
        maxResults: 100,
      }).then(r => ({ ...cal, events: r.data.items || [] }))
    )
  )

  const allEvents = results
    .filter(r => r.status === 'fulfilled')
    .flatMap(r => {
      const val = (r as PromiseFulfilledResult<any>).value
      return val.events.map((e: any) => ({
        id: e.id,
        title: e.summary || '(без названия)',
        start: e.start?.dateTime || e.start?.date,
        end: e.end?.dateTime || e.end?.date,
        allDay: !e.start?.dateTime,
        description: e.description || null,
        location: e.location || null,
        owner: val.owner,
        ownerName: val.name,
        color: val.color,
      }))
    })
    .sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime())

  const errors = results
    .filter(r => r.status === 'rejected')
    .map(r => (r as PromiseRejectedResult).reason?.message || 'unknown')

  return NextResponse.json({ events: allEvents, errors: errors.length ? errors : undefined, fetchedAt: new Date().toISOString() })
}

export async function POST(req: Request) {
  const body = await req.json()
  const { title, date, startTime, endTime, allDay, owner } = body

  const auth = getAuth(false)
  if (!auth) return NextResponse.json({ error: 'not_configured' }, { status: 500 })

  const calendarClient = google.calendar({ version: 'v3', auth: auth as any })

  const daniilCalendarId = process.env.DANIIL_CALENDAR_ID || 'daniilklimov25@gmail.com'
  const svetaCalendarId = process.env.SVETA_CALENDAR_ID || ''

  const calendars: Record<string, { id: string; name: string; color: string }> = {
    daniil: { id: daniilCalendarId, name: 'Даниил', color: '#6366f1' },
    ...(svetaCalendarId ? { sveta: { id: svetaCalendarId, name: 'Света', color: '#ec4899' } } : {}),
  }

  const selectedOwner = owner && calendars[owner] ? owner : 'daniil'
  const cal = calendars[selectedOwner]

  let start: any, end: any
  if (allDay) {
    start = { date, dateTime: null }
    end = { date: nextDayISO(date), dateTime: null }
  } else {
    start = { dateTime: `${date}T${startTime}:00`, timeZone: 'Europe/Moscow', date: null }
    end = { dateTime: `${date}T${endTime}:00`, timeZone: 'Europe/Moscow', date: null }
  }

  try {
    const res = await calendarClient.events.insert({
      calendarId: cal.id,
      requestBody: { summary: title, start, end },
    })
    const e = res.data
    return NextResponse.json({
      event: {
        id: e.id,
        title: e.summary || title,
        start: e.start?.dateTime || e.start?.date,
        end: e.end?.dateTime || e.end?.date,
        allDay: !e.start?.dateTime,
        owner: selectedOwner,
        ownerName: cal.name,
        color: cal.color,
      }
    })
  } catch (err: any) {
    return NextResponse.json({ error: err.message || 'Failed to create event' }, { status: 500 })
  }
}


export async function PUT(req: Request) {
  const body = await req.json()
  const { eventId, title, date, startTime, endTime, allDay, calendarId } = body

  if (!eventId) {
    return NextResponse.json({ error: 'eventId is required' }, { status: 400 })
  }

  const auth = getAuth(false)
  if (!auth) return NextResponse.json({ error: 'not_configured' }, { status: 500 })

  const targetCalendarId = calendarId || process.env.DANIIL_CALENDAR_ID || 'daniilklimov25@gmail.com'
  const calendarClient = google.calendar({ version: 'v3', auth: auth as any })

  let start: any, end: any
  if (allDay) {
    start = { date, dateTime: null }
    end = { date: nextDayISO(date), dateTime: null }
  } else {
    start = { dateTime: `${date}T${startTime}:00`, timeZone: 'Europe/Moscow', date: null }
    end = { dateTime: `${date}T${endTime}:00`, timeZone: 'Europe/Moscow', date: null }
  }

  try {
    const res = await calendarClient.events.patch({
      calendarId: targetCalendarId,
      eventId,
      requestBody: {
        summary: title,
        start,
        end,
      },
    })
    const e = res.data
    return NextResponse.json({
      event: {
        id: e.id,
        title: e.summary || title,
        start: e.start?.dateTime || e.start?.date,
        end: e.end?.dateTime || e.end?.date,
        allDay: !e.start?.dateTime,
      }
    })
  } catch (err: any) {
    return NextResponse.json({ error: err.message || 'Failed to update event' }, { status: 500 })
  }
}
export async function DELETE(req: Request) {
  const { searchParams } = new URL(req.url)
  const eventId = searchParams.get('eventId')
  const calendarId = searchParams.get('calendarId')

  if (!eventId) {
    return NextResponse.json({ error: 'eventId is required' }, { status: 400 })
  }

  const auth = getAuth(false)
  if (!auth) {
    return NextResponse.json({ error: 'not_configured' }, { status: 500 })
  }

  const targetCalendarId = calendarId || process.env.DANIIL_CALENDAR_ID || 'daniilklimov25@gmail.com'
  const calendarClient = google.calendar({ version: 'v3', auth: auth as any })

  try {
    await calendarClient.events.delete({
      calendarId: targetCalendarId,
      eventId,
    })
    return NextResponse.json({ success: true })
  } catch (err: any) {
    return NextResponse.json({ error: err.message || 'Failed to delete event' }, { status: 500 })
  }
}
