import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import TeamDocument from '../models/TeamDocument.js';
import ClubTeam from '../models/ClubTeam.js';
import { devLog } from '../utils/logger.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

class TeamDocumentService {
    /**
     * Speichert ein hochgeladenes Dokument für ein Club-Team
     * @param {Object} file - Das hochgeladene File-Objekt (von multer)
     * @param {number} clubTeamId - Die ID des Club-Teams
     * @param {string} documentType - Der Typ des Dokuments ('code_list' oder 'pin_list')
     * @returns {Promise<TeamDocument>} Das erstellte TeamDocument
     */
    static async uploadDocument(file, clubTeamId, documentType) {
        try {
            // Prüfe ob das Club-Team existiert
            const clubTeam = await ClubTeam.findByPk(clubTeamId);
            if (!clubTeam) {
                throw new Error('Club-Team nicht gefunden');
            }

            // Generiere einen eindeutigen Dateinamen
            const fileExtension = path.extname(file.originalname);
            const uniqueFileName = `${clubTeamId}_${documentType}_${Date.now()}${fileExtension}`;
            
            // Zielverzeichnis für Team-Dokumente
            const uploadDir = path.join(__dirname, '..', 'uploads', 'team-documents');
            
            // Erstelle Upload-Verzeichnis falls es nicht existiert
            if (!fs.existsSync(uploadDir)) {
                fs.mkdirSync(uploadDir, { recursive: true });
            }

            const filePath = path.join(uploadDir, uniqueFileName);

            // Verschiebe die Datei vom temporären Verzeichnis zum finalen Speicherort
            try {
                fs.renameSync(file.path, filePath);
            } catch (error) {
                if (error.code === 'EXDEV') {
                    fs.copyFileSync(file.path, filePath);
                    fs.unlinkSync(file.path);
                } else {
                    throw error;
                }
            }

            // Lösche alte Dokumente des gleichen Typs für dieses Team
            await this.deleteDocumentsByType(clubTeamId, documentType);

            // Erstelle Datenbankeintrag
            const teamDocument = await TeamDocument.create({
                fileName: uniqueFileName,
                originalFileName: file.originalname,
                filePath: filePath,
                fileSize: file.size,
                mimeType: file.mimetype,
                documentType: documentType,
                clubTeamId: clubTeamId
            });

            // In Sequelize wird filePath teils durch das Model-Attribut `path` (Feld-Mapping) überdeckt.
            // Für Controller/Tests stellen wir sicher, dass die Instanz das konkrete Dateisystem-Path als
            // `filePath`-Property trägt.
            try {
                teamDocument.setDataValue('filePath', filePath);
            } catch {
                // ignore
            }

            return teamDocument;
        } catch (error) {
            console.error('[TeamDocumentService.uploadDocument] - Error:', error);
            throw error;
        }
    }

    /**
     * Holt alle Dokumente für ein Club-Team
     * @param {number} clubTeamId - Die ID des Club-Teams
     * @returns {Promise<Array<TeamDocument>>} Liste der Dokumente
     */
    static async getDocumentsByClubTeam(clubTeamId) {
        try {
            
            const documents = await TeamDocument.findAll({
                where: { clubTeamId },
                order: [['createdAt', 'DESC']]
            });

            return documents;
        } catch (error) {
            console.error('[TeamDocumentService.getDocumentsByClubTeam] - Error:', error);
            throw error;
        }
    }

    /**
     * Holt ein spezifisches Dokument
     * @param {number} documentId - Die ID des Dokuments
     * @returns {Promise<TeamDocument|null>} Das Dokument oder null
     */
    static async getDocumentById(documentId) {
        try {
            
            const document = await TeamDocument.findByPk(documentId, {
                include: [{
                    model: ClubTeam,
                    as: 'clubTeam',
                    attributes: ['id', 'name', 'clubId']
                }]
            });
            
            return document;
        } catch (error) {
            console.error('[TeamDocumentService.getDocumentById] - Error:', error);
            throw error;
        }
    }

    /**
     * Löscht ein Dokument
     * @param {number} documentId - Die ID des Dokuments
     * @returns {Promise<boolean>} True wenn gelöscht, sonst false
     */
    static async deleteDocument(documentId) {
        try {
            
            const document = await TeamDocument.findByPk(documentId);
            if (!document) {
                return false;
            }

            // Lösche die physische Datei
            if (fs.existsSync(document.filePath)) {
                fs.unlinkSync(document.filePath);
            }

            // Lösche den Datenbankeintrag
            const deletedRows = await TeamDocument.destroy({
                where: { id: documentId }
            });

            return deletedRows > 0;
        } catch (error) {
            console.error('[TeamDocumentService.deleteDocument] - Error:', error);
            throw error;
        }
    }

    /**
     * Löscht alle Dokumente eines bestimmten Typs für ein Club-Team
     * @param {number} clubTeamId - Die ID des Club-Teams
     * @param {string} documentType - Der Typ des Dokuments
     * @returns {Promise<number>} Anzahl der gelöschten Dokumente
     */
    static async deleteDocumentsByType(clubTeamId, documentType) {
        try {
            
            const documents = await TeamDocument.findAll({
                where: { clubTeamId, documentType }
            });

            let deletedCount = 0;
            for (const document of documents) {
                // Lösche die physische Datei
                if (fs.existsSync(document.filePath)) {
                    fs.unlinkSync(document.filePath);
                }
                deletedCount++;
            }

            // Lösche die Datenbankeinträge
            const deletedRows = await TeamDocument.destroy({
                where: { clubTeamId, documentType }
            });

            return deletedRows;
        } catch (error) {
            console.error('[TeamDocumentService.deleteDocumentsByType] - Error:', error);
            throw error;
        }
    }

    /**
     * Holt den Dateipfad für ein Dokument
     * @param {number} documentId - Die ID des Dokuments
     * @returns {Promise<string|null>} Der Dateipfad oder null
     */
    static async getDocumentPath(documentId) {
        try {
            const document = await TeamDocument.findByPk(documentId);
            return document ? document.filePath : null;
        } catch (error) {
            console.error('[TeamDocumentService.getDocumentPath] - Error:', error);
            throw error;
        }
    }
}

export default TeamDocumentService;
