import { NextRequest, NextResponse } from 'next/server';
import { adminDb } from '@/lib/firebase/admin';
import { exec } from 'child_process';
import { promisify } from 'util';

const execAsync = promisify(exec);

interface TimelineDay {
  date: string; // YYYY-MM-DD format
  dayOfWeek: string;
  gitCommits: Array<{
    hash: string;
    time: string;
    author: string;
    message: string;
    filesChanged: number;
    insertions: number;
    deletions: number;
  }>;
  extensionSessions: Array<{
    startTime: string;
    endTime: string;
    duration: number; // minutes
    filesModified: string[];
    conversationSummary?: string;
  }>;
  cursorMessages: Array<{
    time: string;
    type: 'user' | 'assistant';
    conversationName: string;
    preview: string; // First 100 chars
  }>;
  summary: {
    totalGitCommits: number;
    totalExtensionSessions: number;
    totalCursorMessages: number;
    linesAdded: number;
    linesRemoved: number;
    uniqueFilesModified: number;
  };
}

interface UnifiedTimeline {
  projectId: string;
  dateRange: {
    earliest: string;
    latest: string;
    totalDays: number;
  };
  days: TimelineDay[];
  dataSources: {
    git: { available: boolean; firstDate: string | null; lastDate: string | null; totalRecords: number };
    extension: { available: boolean; firstDate: string | null; lastDate: string | null; totalRecords: number };
    cursor: { available: boolean; firstDate: string | null; lastDate: string | null; totalRecords: number };
  };
}

export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ projectId: string }> }
) {
  try {
    const { projectId } = await params;
    
    // 1. Load Git commits
    const repoPath = '/Users/markhenderson/ai-proxy';
    let gitCommits: any[] = [];
    let gitFirstDate: string | null = null;
    let gitLastDate: string | null = null;

    try {
      const { stdout: commitsOutput } = await execAsync(
        `cd "${repoPath}" && git log --all --pretty=format:"%H|%ai|%an|%s" --numstat`,
        { maxBuffer: 10 * 1024 * 1024 }
      );

      if (commitsOutput.trim()) {
        const lines = commitsOutput.split('\n');
        let currentCommit: any = null;

        for (const line of lines) {
          if (line.includes('|')) {
            if (currentCommit) {
              gitCommits.push(currentCommit);
            }
            const [hash, date, author, message] = line.split('|');
            currentCommit = {
              hash: hash.substring(0, 8),
              date,
              author,
              message,
              filesChanged: 0,
              insertions: 0,
              deletions: 0
            };
          } else if (line.trim() && currentCommit) {
            const parts = line.trim().split('\t');
            if (parts.length === 3) {
              const [insertStr, delStr] = parts;
              const insertions = insertStr === '-' ? 0 : parseInt(insertStr, 10) || 0;
              const deletions = delStr === '-' ? 0 : parseInt(delStr, 10) || 0;
              currentCommit.filesChanged++;
              currentCommit.insertions += insertions;
              currentCommit.deletions += deletions;
            }
          }
        }
        if (currentCommit) {
          gitCommits.push(currentCommit);
        }

        gitCommits.sort((a, b) => new Date(a.date).getTime() - new Date(b.date).getTime());
        if (gitCommits.length > 0) {
          gitFirstDate = gitCommits[0].date;
          gitLastDate = gitCommits[gitCommits.length - 1].date;
        }
      }
    } catch (error) {
      console.log('⚠️ Could not load Git commits:', error);
    }

    // 2. Load Extension sessions
    let extensionSessions: any[] = [];
    let extensionFirstDate: string | null = null;
    let extensionLastDate: string | null = null;

    try {
      // Try to find sessions by projectId first
      let sessionsSnapshot = await adminDb
        .collection('sessions')
        .where('projectId', '==', projectId)
        .get();

      // If no sessions found by projectId, try by workspacePath
      if (sessionsSnapshot.empty) {
        const workspacePath = '/Users/markhenderson/ai-proxy';
        sessionsSnapshot = await adminDb
          .collection('sessions')
          .where('workspacePath', '==', workspacePath)
          .get();
      }

      extensionSessions = sessionsSnapshot.docs.map(doc => {
        const data = doc.data();
        const startTime = data.startTime?.toDate?.() || new Date(data.startTime);
        const endTime = data.endTime?.toDate?.() || new Date(data.endTime);
        
        return {
          startTime,
          endTime,
          filesModified: data.filesModified || [],
          conversationSummary: data.conversationSummary || '',
          conversation: data.conversation || []
        };
      });

      extensionSessions.sort((a, b) => 
        new Date(a.startTime).getTime() - new Date(b.startTime).getTime()
      );

      if (extensionSessions.length > 0) {
        extensionFirstDate = extensionSessions[0].startTime.toISOString();
        extensionLastDate = extensionSessions[extensionSessions.length - 1].endTime.toISOString();
      }
    } catch (error) {
      console.log('⚠️ Could not load extension sessions:', error);
    }

    // 3. Load Cursor messages (from both cursorConversations and extension sessions)
    let cursorMessages: any[] = [];
    let cursorFirstDate: string | null = null;
    let cursorLastDate: string | null = null;

    try {
      // Load from cursorConversations (backfilled historical data)
      const conversationsSnapshot = await adminDb
        .collection('projects')
        .doc(projectId)
        .collection('cursorConversations')
        .get();

      for (const convDoc of conversationsSnapshot.docs) {
        const conv = convDoc.data();
        const messagesSnapshot = await adminDb
          .collection('projects')
          .doc(projectId)
          .collection('cursorConversations')
          .doc(convDoc.id)
          .collection('messages')
          .orderBy('createdAt', 'asc')
          .get();

        const messages = messagesSnapshot.docs.map(msgDoc => {
          const msg = msgDoc.data();
          return {
            createdAt: msg.createdAt,
            type: msg.type === 1 ? 'user' : 'assistant',
            text: msg.text || '',
            conversationName: conv.name || 'Untitled'
          };
        });

        cursorMessages = cursorMessages.concat(messages);
      }

      // Also load from extension sessions conversation data
      for (const session of extensionSessions) {
        if (session.conversation && Array.isArray(session.conversation)) {
          for (const msg of session.conversation) {
            cursorMessages.push({
              createdAt: msg.timestamp || session.startTime.toISOString(),
              type: msg.role === 'user' ? 'user' : 'assistant',
              text: msg.message || '',
              conversationName: 'Extension Session'
            });
          }
        }
      }

      cursorMessages.sort((a, b) => 
        new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
      );

      if (cursorMessages.length > 0) {
        cursorFirstDate = cursorMessages[0].createdAt;
        cursorLastDate = cursorMessages[cursorMessages.length - 1].createdAt;
      }
    } catch (error) {
      console.log('⚠️ Could not load Cursor messages:', error);
    }

    // 4. Find overall date range
    const allFirstDates = [
      gitFirstDate ? new Date(gitFirstDate) : null,
      extensionFirstDate ? new Date(extensionFirstDate) : null,
      cursorFirstDate ? new Date(cursorFirstDate) : null
    ].filter(d => d !== null) as Date[];

    const allLastDates = [
      gitLastDate ? new Date(gitLastDate) : null,
      extensionLastDate ? new Date(extensionLastDate) : null,
      cursorLastDate ? new Date(cursorLastDate) : null
    ].filter(d => d !== null) as Date[];

    if (allFirstDates.length === 0 && allLastDates.length === 0) {
      return NextResponse.json({
        error: 'No timeline data available',
        projectId,
        dateRange: { earliest: null, latest: null, totalDays: 0 },
        days: [],
        dataSources: {
          git: { available: false, firstDate: null, lastDate: null, totalRecords: 0 },
          extension: { available: false, firstDate: null, lastDate: null, totalRecords: 0 },
          cursor: { available: false, firstDate: null, lastDate: null, totalRecords: 0 }
        }
      });
    }

    const earliestDate = new Date(Math.min(...allFirstDates.map(d => d.getTime())));
    const latestDate = new Date(Math.max(...allLastDates.map(d => d.getTime())));
    const totalDays = Math.ceil((latestDate.getTime() - earliestDate.getTime()) / (1000 * 60 * 60 * 24)) + 1;

    // 5. Group data by day
    const dayMap = new Map<string, TimelineDay>();

    // Initialize all days
    for (let i = 0; i < totalDays; i++) {
      const date = new Date(earliestDate);
      date.setDate(date.getDate() + i);
      const dateKey = date.toISOString().split('T')[0];
      const dayOfWeek = date.toLocaleDateString('en-US', { weekday: 'long' });

      dayMap.set(dateKey, {
        date: dateKey,
        dayOfWeek,
        gitCommits: [],
        extensionSessions: [],
        cursorMessages: [],
        summary: {
          totalGitCommits: 0,
          totalExtensionSessions: 0,
          totalCursorMessages: 0,
          linesAdded: 0,
          linesRemoved: 0,
          uniqueFilesModified: 0
        }
      });
    }

    // Add Git commits to days
    for (const commit of gitCommits) {
      const dateKey = commit.date.split(' ')[0];
      const day = dayMap.get(dateKey);
      if (day) {
        day.gitCommits.push({
          hash: commit.hash,
          time: commit.date,
          author: commit.author,
          message: commit.message,
          filesChanged: commit.filesChanged,
          insertions: commit.insertions,
          deletions: commit.deletions
        });
        day.summary.totalGitCommits++;
        day.summary.linesAdded += commit.insertions;
        day.summary.linesRemoved += commit.deletions;
      }
    }

    // Add Extension sessions to days
    for (const session of extensionSessions) {
      const dateKey = new Date(session.startTime).toISOString().split('T')[0];
      const day = dayMap.get(dateKey);
      if (day) {
        const startTime = new Date(session.startTime);
        const endTime = new Date(session.endTime);
        const duration = Math.round((endTime.getTime() - startTime.getTime()) / (1000 * 60));

        day.extensionSessions.push({
          startTime: session.startTime.toISOString(),
          endTime: session.endTime.toISOString(),
          duration,
          filesModified: session.filesModified,
          conversationSummary: session.conversationSummary
        });
        day.summary.totalExtensionSessions++;

        // Track unique files
        const uniqueFiles = new Set([...session.filesModified]);
        day.summary.uniqueFilesModified += uniqueFiles.size;
      }
    }

    // Add Cursor messages to days
    for (const message of cursorMessages) {
      const dateKey = new Date(message.createdAt).toISOString().split('T')[0];
      const day = dayMap.get(dateKey);
      if (day) {
        day.cursorMessages.push({
          time: message.createdAt,
          type: message.type,
          conversationName: message.conversationName,
          preview: message.text.substring(0, 100)
        });
        day.summary.totalCursorMessages++;
      }
    }

    // Convert to array and sort by date
    const days = Array.from(dayMap.values()).sort((a, b) => 
      new Date(a.date).getTime() - new Date(b.date).getTime()
    );

    const timeline: UnifiedTimeline = {
      projectId,
      dateRange: {
        earliest: earliestDate.toISOString(),
        latest: latestDate.toISOString(),
        totalDays
      },
      days,
      dataSources: {
        git: {
          available: gitCommits.length > 0,
          firstDate: gitFirstDate,
          lastDate: gitLastDate,
          totalRecords: gitCommits.length
        },
        extension: {
          available: extensionSessions.length > 0,
          firstDate: extensionFirstDate,
          lastDate: extensionLastDate,
          totalRecords: extensionSessions.length
        },
        cursor: {
          available: cursorMessages.length > 0,
          firstDate: cursorFirstDate,
          lastDate: cursorLastDate,
          totalRecords: cursorMessages.length
        }
      }
    };

    return NextResponse.json(timeline);

  } catch (error) {
    console.error('Error generating unified timeline:', error);
    return NextResponse.json(
      { 
        error: 'Failed to generate unified timeline',
        details: error instanceof Error ? error.message : String(error)
      },
      { status: 500 }
    );
  }
}

