/**
 * METRC Integration Service
 * 
 * Handles synchronization between facility plant addresses and METRC locations.
 * California METRC requires plant location tracking in a specific format.
 */

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// METRC Address Format: Building-Room-Section-Position (e.g., "BLDG1-VEG1-T1-R1C5")
export interface MetrcLocation {
    plantId: string;
    tagNumber: string;
    metrcTag?: string;
    location: string;
    room: string;
    section?: string;
    position?: string;
}

/**
 * Convert internal address to METRC-compatible format
 * Internal: VEG1-T1-1-5 (Room-Section-Row-Column)
 * METRC: VEG1-T1-R1C5 (Room-Section-Row/Col combined)
 */
export function formatAddressForMetrc(address: string): string {
    const parts = address.split('-');
    if (parts.length < 4) return address;

    const [room, section, row, col] = parts;
    return `${room}-${section}-R${row}C${col}`;
}

/**
 * Parse METRC location back to internal format
 */
export function parseMetrcLocation(metrcLocation: string): { room: string; section: string; row: number; column: number } | null {
    const match = metrcLocation.match(/^([A-Z0-9]+)-([A-Z0-9]+)-R(\d+)C(\d+)$/);
    if (!match) return null;

    return {
        room: match[1],
        section: match[2],
        row: parseInt(match[3]),
        column: parseInt(match[4])
    };
}

/**
 * Generate METRC location report for all plants
 */
export async function generateMetrcLocationReport(propertyId?: string): Promise<MetrcLocation[]> {
    const plants = await prisma.facilityPlant.findMany({
        where: propertyId ? {
            position: {
                section: {
                    room: {
                        floor: {
                            building: { propertyId }
                        }
                    }
                }
            }
        } : undefined,
        include: {
            position: {
                include: {
                    section: {
                        include: {
                            room: true
                        }
                    }
                }
            }
        }
    });

    return plants.map(plant => ({
        plantId: plant.id,
        tagNumber: plant.tagNumber,
        metrcTag: (plant as any).metrcTag || undefined,
        location: formatAddressForMetrc(plant.address),
        room: plant.position?.section?.room?.code || 'UNKNOWN',
        section: plant.position?.section?.code,
        position: plant.position ? `R${plant.position.row}C${plant.position.column}` : undefined
    }));
}

/**
 * Detect discrepancies between internal records and METRC
 * (Placeholder - requires actual METRC API integration)
 */
export interface MetrcDiscrepancy {
    plantId: string;
    tagNumber: string;
    type: 'MISSING_IN_METRC' | 'MISSING_LOCALLY' | 'LOCATION_MISMATCH' | 'STATUS_MISMATCH';
    internalValue?: string;
    metrcValue?: string;
    severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
}

export async function detectMetrcDiscrepancies(metrcData: any[]): Promise<MetrcDiscrepancy[]> {
    const discrepancies: MetrcDiscrepancy[] = [];

    // Get all local plants
    const localPlants = await prisma.facilityPlant.findMany({
        include: {
            position: {
                include: {
                    section: {
                        include: { room: true }
                    }
                }
            }
        }
    });

    const localByTag = new Map(localPlants.map(p => [p.tagNumber, p]));
    const metrcByTag = new Map(metrcData.map(m => [m.tag, m]));

    // Check for plants missing in METRC
    for (const plant of localPlants) {
        if (!metrcByTag.has(plant.tagNumber)) {
            discrepancies.push({
                plantId: plant.id,
                tagNumber: plant.tagNumber,
                type: 'MISSING_IN_METRC',
                internalValue: plant.address,
                severity: 'CRITICAL'
            });
        }
    }

    // Check for plants missing locally
    for (const [tag, metrcPlant] of metrcByTag) {
        if (!localByTag.has(tag)) {
            discrepancies.push({
                plantId: '',
                tagNumber: tag,
                type: 'MISSING_LOCALLY',
                metrcValue: metrcPlant.location,
                severity: 'HIGH'
            });
        }
    }

    // Check for location mismatches
    for (const plant of localPlants) {
        const metrc = metrcByTag.get(plant.tagNumber);
        if (metrc) {
            const internalLocation = formatAddressForMetrc(plant.address);
            if (metrc.location !== internalLocation) {
                discrepancies.push({
                    plantId: plant.id,
                    tagNumber: plant.tagNumber,
                    type: 'LOCATION_MISMATCH',
                    internalValue: internalLocation,
                    metrcValue: metrc.location,
                    severity: 'MEDIUM'
                });
            }
        }
    }

    return discrepancies;
}

/**
 * Sync plant location to METRC
 * (Placeholder - requires actual METRC API credentials)
 */
export async function syncPlantLocationToMetrc(plantId: string): Promise<{ success: boolean; error?: string }> {
    const plant = await prisma.facilityPlant.findUnique({
        where: { id: plantId },
        include: {
            position: {
                include: {
                    section: {
                        include: { room: true }
                    }
                }
            }
        }
    });

    if (!plant) {
        return { success: false, error: 'Plant not found' };
    }

    const metrcLocation = formatAddressForMetrc(plant.address);

    // TODO: Implement actual METRC API call
    // const metrcApi = new MetrcApiClient(process.env.METRC_API_KEY);
    // await metrcApi.updatePlantLocation(plant.metrcTag, metrcLocation);

    console.log(`[METRC SYNC] Would update plant ${plant.tagNumber} to location ${metrcLocation}`);

    return { success: true };
}

/**
 * Bulk sync all plant locations to METRC
 */
export async function bulkSyncLocationsToMetrc(propertyId?: string): Promise<{ synced: number; errors: string[] }> {
    const report = await generateMetrcLocationReport(propertyId);
    const errors: string[] = [];
    let synced = 0;

    for (const plant of report) {
        const result = await syncPlantLocationToMetrc(plant.plantId);
        if (result.success) {
            synced++;
        } else {
            errors.push(`${plant.tagNumber}: ${result.error}`);
        }
    }

    return { synced, errors };
}
