import fs from 'fs';
import csv from 'csv-parser';
import { parse } from 'date-fns';
import iconv from 'iconv-lite';
import Match from '../models/Match.js';
import Season from '../models/Season.js';
import Location from '../models/Location.js';
import League from '../models/League.js';
import Team from '../models/Team.js';
import { checkAccess } from '../utils/userUtils.js';
import { Op } from 'sequelize';

class MatchService {

    generateSeasonString(date = new Date()) {
        const currentYear = date.getFullYear();
        let seasonStartYear;
        if (date >= new Date(currentYear, 6, 1)) {
            seasonStartYear = currentYear;
        } else {
            seasonStartYear = currentYear - 1;
        }
        const seasonEndYear = seasonStartYear + 1;
        const seasonEndYearString = seasonEndYear.toString().slice(-2);
        return `${seasonStartYear}/${seasonEndYearString}`;
    }

    async importCSV(userToken, clubId, filePath) {
        await checkAccess(userToken, clubId);
        let seasonString = '';
        const matches = [];
        try {
            const fileStream = fs.createReadStream(filePath)
                .pipe(iconv.decodeStream('ISO-8859-15'))
                .pipe(csv({ separator: ';' }));
            for await (const row of fileStream) {
                const parsedDate = parse(row['Termin'], 'dd.MM.yyyy HH:mm', new Date());
                seasonString = this.generateSeasonString(parsedDate);
                const [season] = await Season.findOrCreate({
                    where: { season: seasonString },
                });
                const [league] = await League.findOrCreate({
                    where: {
                        name: row['Staffel'],
                        clubId: clubId,
                        seasonId: season.id,
                    },
                });
                const homeTeamId = await this.getOrCreateTeamId(row['HeimMannschaft'], clubId);
                const guestTeamId = await this.getOrCreateTeamId(row['GastMannschaft'], clubId);
                const [location] = await Location.findOrCreate({
                    where: {
                        name: row['HalleName'],
                        address: row['HalleStrasse'],
                        city: row['HalleOrt'],
                        zip: row['HallePLZ'],
                    },
                });
                matches.push({
                    seasonId: season.id,
                    date: parsedDate,
                    time: row['Termin'].split(' ')[1],
                    homeTeamId: homeTeamId,
                    guestTeamId: guestTeamId,
                    leagueId: league.id,
                    locationId: location.id,
                    clubId: clubId,
                });
            }
            if (seasonString) {
                const season = await Season.findOne({ where: { season: seasonString } });
                if (season) {
                    await Match.destroy({
                        where: {
                            clubId: clubId,
                            seasonId: season.id,
                        }
                    });
                }
            }
            const result = await Match.bulkCreate(matches);
            return result;

        } catch (error) {
            console.log('Error during CSV import:', error);
            throw error;
        }
    }

    async getOrCreateTeamId(teamName, clubId) {
        const [team] = await Team.findOrCreate({
            where: {
                name: teamName,
                clubId: clubId
            },
            defaults: {
                name: teamName,
                clubId: clubId
            }
        });
        return team.id;
    }


    async getLeaguesForCurrentSeason(userToken, clubId) {
        await checkAccess(userToken, clubId);
        const seasonString = this.generateSeasonString();
        const season = await Season.findOne({
            where: {
                season: {
                    [Op.like]: `%${seasonString}%`
                }
            }
        });
        if (!season) {
	    await Season.create({ season: seasonString });
            throw new Error('Season not found');
        }
        try {
            const leagues = await League.findAll({
                include: [{
                    model: Match,
                    as: 'leagueMatches',  
                    where: {
                        seasonId: season.id,
                        clubId: clubId
                    },
                    attributes: [],
                }],
                attributes: ['id', 'name'],
                group: ['League.id'],
            });
            return leagues;
        } catch (error) {
            console.error('Error retrieving leagues:', error);
            throw new Error('Failed to retrieve leagues');
        }
    }

    async getMatchesForLeagues(userToken, clubId) {
        await checkAccess(userToken, clubId);
        const seasonString = this.generateSeasonString();
        const season = await Season.findOne({
            where: {
                season: {
                    [Op.like]: `%${seasonString}%`
                }
            }
        });
        if (!season) {
            throw new Error('Season not found');
        }
        const matches = await Match.findAll({
            where: {
                seasonId: season.id,
                clubId: clubId,
            },
            include: [
                {
                    model: League,
                    as: 'leagueDetails',
                    attributes: ['name'],
                },
                {
                    model: Team,
                    as: 'homeTeam', // Assuming your associations are set correctly
                    attributes: ['name'],
                },
                {
                    model: Team,
                    as: 'guestTeam',
                    attributes: ['name'],
                },
                {
                    model: Location,
                    as: 'location',
                    attributes: ['name', 'address', 'city', 'zip'],
                }
            ]
        });
        return matches;
    }

    async getMatchesForLeague(userToken, clubId, leagueId) {
        await checkAccess(userToken, clubId);
        const seasonString = this.generateSeasonString();
        const season = await Season.findOne({
            where: {
                season: {
                    [Op.like]: `%${seasonString}%`
                }
            }
        });
        if (!season) {
            throw new Error('Season not found');
        }
        const matches = await Match.findAll({
            where: {
                seasonId: season.id,
                clubId: clubId,
                leagueId: leagueId
            },
            include: [
                {
                    model: League,
                    as: 'leagueDetails',
                    attributes: ['name'],
                },
                {
                    model: Team,
                    as: 'homeTeam', 
                    attributes: ['name'],
                },
                {
                    model: Team,
                    as: 'guestTeam',
                    attributes: ['name'],
                },
                {
                    model: Location,
                    as: 'location',
                    attributes: ['name', 'address', 'city', 'zip'],
                }
            ]
        });
        return matches;
    }

}

export default new MatchService();

