import { directus } from './directus.js'
import { cryptoService } from './crypto.js'

const CACHE_TTL = 5 * 60 * 1000

class ReputationService {
    constructor() {
        this.cache = new Map()
    }

    async getUserHash() {
        await cryptoService.ready
        const publicKey = cryptoService.getPublicKey()
        const encoder = new TextEncoder()
        const data = encoder.encode(publicKey)
        const hash = await crypto.subtle.digest('SHA-256', data)
        return Array.from(new Uint8Array(hash))
            .map(b => b.toString(16).padStart(2, '0'))
            .join('')
    }

    // ── Deals ──

    async createDeal(conversation) {
        const userHash = await this.getUserHash()

        // participant_hash_1 = buyer (initiator), participant_hash_2 = seller
        const sellerHash = conversation.participant_hash_2
        const buyerHash = conversation.participant_hash_1
        const isSeller = sellerHash === userHash

        const response = await directus.post('/items/deals', {
            conversation: conversation.id,
            listing: conversation.listing_id,
            seller_hash: sellerHash,
            buyer_hash: buyerHash,
            status: 'pending',
            seller_confirmed: isSeller,
            buyer_confirmed: !isSeller
        })

        return response.data || response
    }

    async confirmDeal(dealId) {
        const userHash = await this.getUserHash()
        const deal = await this.getDeal(dealId)

        if (!deal) throw new Error('Deal not found')

        const isSeller = deal.seller_hash === userHash
        const isBuyer = deal.buyer_hash === userHash
        if (!isSeller && !isBuyer) throw new Error('Not a participant of this deal')

        const update = {}
        if (isSeller) update.seller_confirmed = true
        if (isBuyer) update.buyer_confirmed = true

        const sellerConfirmed = isSeller ? true : deal.seller_confirmed
        const buyerConfirmed = isBuyer ? true : deal.buyer_confirmed

        if (sellerConfirmed && buyerConfirmed) {
            update.status = 'confirmed'
            update.date_confirmed = new Date().toISOString()
        }

        const response = await directus.patch(`/items/deals/${dealId}`, update)
        this.clearCache()
        return response.data || response
    }

    async getDeal(dealId) {
        const response = await directus.get(`/items/deals/${dealId}`)
        return response.data || response
    }

    async getDealsForConversation(conversationId) {
        const response = await directus.get('/items/deals', {
            filter: { conversation: { _eq: conversationId } },
            sort: ['-date_created']
        })
        return response.data || []
    }

    async getDealsForUser(userHash) {
        const response = await directus.get('/items/deals', {
            filter: {
                status: { _eq: 'confirmed' },
                _or: [
                    { seller_hash: { _eq: userHash } },
                    { buyer_hash: { _eq: userHash } }
                ]
            },
            sort: ['-date_confirmed']
        })
        return response.data || []
    }

    // ── Ratings ──

    async rateDeal(dealId, score) {
        if (score < 1 || score > 5) throw new Error('Score must be between 1 and 5')

        const deal = await this.getDeal(dealId)
        if (!deal) throw new Error('Deal not found')
        if (deal.status !== 'confirmed') throw new Error('Deal must be confirmed before rating')

        const userHash = await this.getUserHash()
        const isSeller = deal.seller_hash === userHash
        const isBuyer = deal.buyer_hash === userHash
        if (!isSeller && !isBuyer) throw new Error('Not a participant of this deal')

        const ratedUserHash = isSeller ? deal.buyer_hash : deal.seller_hash

        const existing = await directus.get('/items/ratings', {
            filter: {
                deal: { _eq: dealId },
                rater_hash: { _eq: userHash }
            },
            limit: 1
        })

        if (existing.data?.length > 0) throw new Error('Already rated this deal')

        const response = await directus.post('/items/ratings', {
            deal: dealId,
            rater_hash: userHash,
            rated_hash: ratedUserHash,
            score,
            date_created: new Date().toISOString()
        })

        this.clearCache()
        return response.data || response
    }

    async getRatingsForUser(userHash) {
        const response = await directus.get('/items/ratings', {
            filter: { rated_hash: { _eq: userHash } },
            sort: ['-date_created']
        })
        return response.data || []
    }

    // ── Reputation ──

    async getReputation(userHash) {
        const cached = this.cache.get(userHash)
        if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
            return cached.value
        }

        const [deals, ratings] = await Promise.all([
            this.getDealsForUser(userHash),
            this.getRatingsForUser(userHash)
        ])

        const dealsCompleted = deals.length
        const avgRating = ratings.length > 0
            ? ratings.reduce((sum, r) => sum + r.score, 0) / ratings.length
            : 0

        let accountAgeDays = 0
        const dates = deals.map(d => d.date_confirmed || d.date_created).filter(Boolean)

        if (dates.length > 0) {
            const oldest = dates
                .map(d => new Date(d).getTime())
                .reduce((min, t) => Math.min(min, t), Infinity)
            accountAgeDays = Math.floor((Date.now() - oldest) / (1000 * 60 * 60 * 24))
        }

        let level = 'new'
        if (dealsCompleted >= 30 && avgRating >= 4.5) {
            level = 'power'
        } else if (dealsCompleted >= 10 && avgRating >= 4.0) {
            level = 'trusted'
        } else if (dealsCompleted >= 3 && accountAgeDays >= 30) {
            level = 'active'
        }

        const reputation = {
            deals_completed: dealsCompleted,
            avg_rating: Math.round(avgRating * 100) / 100,
            account_age_days: accountAgeDays,
            level
        }

        this.cache.set(userHash, { value: reputation, timestamp: Date.now() })
        return reputation
    }

    getLevelInfo(level) {
        const levels = {
            new: { badge: '⚪', i18nKey: 'reputation.level.new' },
            active: { badge: '🔵', i18nKey: 'reputation.level.active' },
            trusted: { badge: '🟢', i18nKey: 'reputation.level.trusted' },
            power: { badge: '🟣', i18nKey: 'reputation.level.power' }
        }
        return levels[level] || levels.new
    }

    clearCache() {
        this.cache.clear()
    }
}

export const reputationService = new ReputationService()
