import { jumps, type Jump, type InsertJump, type JumpQuery } from "@shared/schema";

export interface IStorage {
  getAllJumps(): Promise<Jump[]>;
  getJumps(query: JumpQuery): Promise<{ jumps: Jump[], total: number }>;
  getJump(id: number): Promise<Jump | undefined>;
  createJump(jump: InsertJump): Promise<Jump>;
  createJumps(jumpsData: InsertJump[]): Promise<Jump[]>;
  updateJump(id: number, jump: Partial<InsertJump>): Promise<Jump | undefined>;
  deleteJump(id: number): Promise<boolean>;
  getStatistics(): Promise<{
    totalJumps: number,
    dropzones: number,
    maxAltitude: string,
    avgAltitude: string,
    aircraftTypes: number,
    topDropzone: string,
    topAircraft: string,
    monthlyIncrease: number
  }>;
}

export class MemStorage implements IStorage {
  private jumpRecords: Map<number, Jump>;
  private currentId: number;

  constructor() {
    this.jumpRecords = new Map();
    this.currentId = 1;
  }

  async getAllJumps(): Promise<Jump[]> {
    return Array.from(this.jumpRecords.values());
  }

  async getJumps(query: JumpQuery): Promise<{ jumps: Jump[], total: number }> {
    let allJumps = Array.from(this.jumpRecords.values());
    
    // Apply search filter
    if (query.search) {
      const searchTerm = query.search.toLowerCase();
      allJumps = allJumps.filter(jump => {
        // Format date for searching in format YYYY-MM-DD
        const jumpDate = new Date(jump.jumpDate);
        const formattedDate = jumpDate.toISOString().split('T')[0];
          
        return jump.jumpType.toLowerCase().includes(searchTerm) ||
          jump.dropzone.toLowerCase().includes(searchTerm) ||
          jump.aircraft.toLowerCase().includes(searchTerm) ||
          jump.equipment.toLowerCase().includes(searchTerm) ||
          formattedDate.includes(searchTerm) ||
          (jump.notes && jump.notes.toLowerCase().includes(searchTerm));
      });
    }
    
    // Apply dropzone filter
    if (query.dropzone) {
      allJumps = allJumps.filter(jump => 
        jump.dropzone.toLowerCase() === query.dropzone?.toLowerCase()
      );
    }
    
    // Apply sorting
    if (query.sort) {
      const [field, direction] = query.sort.split(':');
      const isDesc = direction === 'desc';
      
      allJumps.sort((a: any, b: any) => {
        if (field === 'jumpNumber') {
          return isDesc ? b[field] - a[field] : a[field] - b[field];
        } else {
          const valA = String(a[field]).toLowerCase();
          const valB = String(b[field]).toLowerCase();
          return isDesc ? valB.localeCompare(valA) : valA.localeCompare(valB);
        }
      });
    } else {
      // Default sort by jump number desc
      allJumps.sort((a, b) => b.jumpNumber - a.jumpNumber);
    }
    
    const total = allJumps.length;
    
    // Apply pagination
    const page = query.page || 1;
    const limit = query.limit || 10;
    const start = (page - 1) * limit;
    const end = start + limit;
    
    return {
      jumps: allJumps.slice(start, end),
      total
    };
  }

  async getJump(id: number): Promise<Jump | undefined> {
    return this.jumpRecords.get(id);
  }

  async createJump(jump: InsertJump): Promise<Jump> {
    const id = this.currentId++;
    // Ensure notes is null if undefined
    const newJump: Jump = { 
      id, 
      ...jump,
      notes: jump.notes || null 
    };
    this.jumpRecords.set(id, newJump);
    return newJump;
  }

  async createJumps(jumpsData: InsertJump[]): Promise<Jump[]> {
    const createdJumps: Jump[] = [];

    for (const jumpData of jumpsData) {
      const id = this.currentId++;
      const newJump: Jump = { 
        id, 
        ...jumpData,
        notes: jumpData.notes || null 
      };
      this.jumpRecords.set(id, newJump);
      createdJumps.push(newJump);
    }

    return createdJumps;
  }

  async updateJump(id: number, jump: Partial<InsertJump>): Promise<Jump | undefined> {
    const existingJump = this.jumpRecords.get(id);
    
    if (!existingJump) {
      return undefined;
    }
    
    const updatedJump = { ...existingJump, ...jump };
    this.jumpRecords.set(id, updatedJump);
    
    return updatedJump;
  }

  async deleteJump(id: number): Promise<boolean> {
    return this.jumpRecords.delete(id);
  }

  async getStatistics(): Promise<{
    totalJumps: number,
    dropzones: number,
    maxAltitude: string,
    avgAltitude: string,
    aircraftTypes: number,
    topDropzone: string,
    topAircraft: string,
    monthlyIncrease: number
  }> {
    const jumps = Array.from(this.jumpRecords.values());
    
    // Get unique dropzones, aircraft, and equipment
    const dropzones = new Set(jumps.map(jump => jump.dropzone));
    const aircraftTypes = new Set(jumps.map(jump => jump.aircraft));
    
    // Get max and average altitude
    let maxAlt = 0;
    let totalAlt = 0;
    
    jumps.forEach(jump => {
      const alt = parseInt(jump.altitude.replace(/[^\d]/g, ''), 10);
      if (!isNaN(alt)) {
        maxAlt = Math.max(maxAlt, alt);
        totalAlt += alt;
      }
    });
    
    const avgAlt = jumps.length > 0 ? Math.round(totalAlt / jumps.length) : 0;
    
    // Count jumps by dropzone and aircraft to find the most common
    const dzCounts: Record<string, number> = {};
    const aircraftCounts: Record<string, number> = {};
    
    jumps.forEach(jump => {
      dzCounts[jump.dropzone] = (dzCounts[jump.dropzone] || 0) + 1;
      aircraftCounts[jump.aircraft] = (aircraftCounts[jump.aircraft] || 0) + 1;
    });
    
    let topDropzone = '';
    let maxDzCount = 0;
    
    for (const [dz, count] of Object.entries(dzCounts)) {
      if (count > maxDzCount) {
        maxDzCount = count;
        topDropzone = dz;
      }
    }
    
    let topAircraft = '';
    let maxAircraftCount = 0;
    
    for (const [aircraft, count] of Object.entries(aircraftCounts)) {
      if (count > maxAircraftCount) {
        maxAircraftCount = count;
        topAircraft = aircraft;
      }
    }
    
    // Calculate monthly increase based on jump dates
    const currentDate = new Date();
    const currentMonth = currentDate.getMonth();
    const currentYear = currentDate.getFullYear();
    
    // Get jumps from current month and previous month
    const currentMonthJumps = jumps.filter(jump => {
      const jumpDate = new Date(jump.jumpDate);
      return jumpDate.getMonth() === currentMonth && jumpDate.getFullYear() === currentYear;
    });
    
    const previousMonth = currentMonth === 0 ? 11 : currentMonth - 1;
    const previousMonthYear = currentMonth === 0 ? currentYear - 1 : currentYear;
    
    const previousMonthJumps = jumps.filter(jump => {
      const jumpDate = new Date(jump.jumpDate);
      return jumpDate.getMonth() === previousMonth && jumpDate.getFullYear() === previousMonthYear;
    });
    
    // Calculate percentage increase
    let monthlyIncrease = 0;
    if (previousMonthJumps.length > 0) {
      const increase = currentMonthJumps.length - previousMonthJumps.length;
      monthlyIncrease = Math.round((increase / previousMonthJumps.length) * 100);
    } else if (currentMonthJumps.length > 0) {
      // If no jumps last month but some this month, that's a 100% increase
      monthlyIncrease = 100;
    }
    
    return {
      totalJumps: jumps.length,
      dropzones: dropzones.size,
      maxAltitude: `${maxAlt.toLocaleString()} ft`,
      avgAltitude: `${avgAlt.toLocaleString()} ft`,
      aircraftTypes: aircraftTypes.size,
      topDropzone,
      topAircraft,
      monthlyIncrease
    };
  }
}

export const storage = new MemStorage();
