/**
 * Chat Widget Component
 * Embedded chat for buyer-seller communication using Directus conversations
 */

import { t, i18n } from '../i18n.js'
import { conversationsService } from '../services/conversations.js'
import { cryptoService } from '../services/crypto.js'
import { keyPinningService } from '../services/key-pinning.js'
import { escapeHTML } from '../utils/helpers.js'
import { reputationService } from '../services/reputation.js'

class ChatWidget extends HTMLElement {
    static get observedAttributes() {
        return ['listing-id', 'recipient-name', 'seller-public-key', 'conversation-id']
    }

    constructor() {
        super()
        this.conversation = null
        this.messages = []
        this.unsubscribe = null
        this.loading = true
        this.error = null
        this._initialized = false
        this.deal = null
        this.hasRated = false
        this.mySecretKey = null
        this.keyWarning = false
    }

    connectedCallback() {
        this.listingId = this.getAttribute('listing-id')
        this.recipientName = this.getAttribute('recipient-name') || 'Seller'
        this.sellerPublicKey = this.getAttribute('seller-public-key')
        this.conversationId = this.getAttribute('conversation-id')
        this.render()
    }

    disconnectedCallback() {
        if (this.unsubscribe) this.unsubscribe()
        if (this.i18nUnsubscribe) this.i18nUnsubscribe()
    }

    async activate() {
        if (this._initialized) return
        this._initialized = true

        this.conversationId = this.getAttribute('conversation-id') || this.conversationId
        await cryptoService.ready

        if (!cryptoService.getPublicKey()) {
            this.loading = false
            this.error = 'no-keypair'
            this.render()
            return
        }

        if (this.listingId) {
            await this.initConversation()
        } else {
            this.loading = false
            this.error = 'missing-data'
            this.render()
        }

        this.unsubscribe = conversationsService.subscribe(() => this.refreshMessages())
        this.i18nUnsubscribe = i18n.subscribe(() => this.render())
    }

    async initConversation() {
        try {
            if (this.conversationId) {
                this.conversation = await conversationsService.getConversation(this.conversationId)
                if (!this.conversation) {
                    this.error = 'init-failed'
                    this.loading = false
                    this.render()
                    return
                }
                this.mySecretKey = await conversationsService.getMySecretKeyForConversation(this.conversation)
                await this.loadMessages()
                await this.loadDealState()
            } else {
                if (!this.sellerPublicKey) {
                    this.error = 'no-seller-key'
                    this.loading = false
                    this.render()
                    return
                }

                const pinStatus = keyPinningService.check(this.listingId, this.sellerPublicKey)
                if (pinStatus === 'changed') {
                    this.keyWarning = true
                    this.loading = false
                    this.render()
                    this.setupEventListeners()
                    return
                }

                this.conversation = await conversationsService.startOrGetConversation(this.listingId, this.sellerPublicKey)
                this.mySecretKey = await conversationsService.getMySecretKeyForConversation(this.conversation)
                await this.loadMessages()
                await this.loadDealState()
            }
        } catch (e) {
            console.error('Failed to init conversation:', e)
            this.error = 'init-failed'
        }
        this.loading = false
        this.render()
        this.setupEventListeners()
    }

    async acceptKeyChange() {
        keyPinningService.acceptChange(this.listingId, this.sellerPublicKey)
        this.keyWarning = false
        this.loading = true
        this.render()
        await this.initConversation()
    }

    async loadMessages() {
        if (!this.conversation) return
        this.messages = await conversationsService.getMessages(
            this.conversation.id,
            this.conversation.otherPublicKey,
            this.mySecretKey
        )
    }

    async refreshMessages() {
        await this.loadMessages()
        this.renderMessages()
        this.scrollToBottom()
    }

    async loadDealState() {
        if (!this.conversation) return
        try {
            const deals = await reputationService.getDealsForConversation(this.conversation.id)
            this.deal = deals[0] || null
            this._cachedUserHash = await reputationService.getUserHash()
            if (this.deal && this.deal.status === 'confirmed') {
                const userHash = this._cachedUserHash
                const ratings = await reputationService.getRatingsForUser(
                    this.deal.seller_hash === userHash ? this.deal.buyer_hash : this.deal.seller_hash
                )
                this.hasRated = ratings.some(r => r.deal === this.deal.id && r.rater_hash === userHash)
            }
        } catch (e) {
            console.error('Failed to load deal state:', e)
        }
    }

    render() {
        if (this.loading) {
            this.innerHTML = /* html */`
                <div class="chat-widget">
                    <div class="chat-loading">
                        <span>${t('common.loading')}</span>
                    </div>
                </div>
            `
            return
        }

        if (this.error) {
            this.innerHTML = /* html */`
                <div class="chat-widget">
                    <div class="chat-error">
                        <p>${t('chat.unavailable')}</p>
                    </div>
                </div>
            `
            return
        }

        if (this.keyWarning) {
            this.innerHTML = /* html */`
                <div class="chat-widget">
                    <div class="chat-key-warning">
                        <div class="key-warning-icon">⚠</div>
                        <h4>${t('chat.keyChanged')}</h4>
                        <p>${t('chat.keyChangedHint')}</p>
                        <div class="key-warning-actions">
                            <button class="btn btn-outline" id="key-accept-btn">${t('chat.keyAccept')}</button>
                        </div>
                    </div>
                </div>
            `
            return
        }

        this.innerHTML = /* html */`
            <div class="chat-widget">
                <div class="chat-header">
                    <span class="chat-recipient">${escapeHTML(this.recipientName)}</span>
                    <span class="chat-encrypted" title="${t('chat.encrypted')}">🔒</span>
                </div>
                
                <div class="chat-messages" id="chat-messages">
                    ${this.renderMessagesHtml()}
                </div>
                
                ${this.renderDealSection()}
                
                <form class="chat-input" id="chat-form">
                    <input 
                        type="text" 
                        id="message-input" 
                        placeholder="${t('chat.placeholder')}"
                        autocomplete="off"
                    >
                    <button type="submit" class="btn btn-primary">
                        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                            <line x1="22" y1="2" x2="11" y2="13"></line>
                            <polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
                        </svg>
                    </button>
                </form>
            </div>
        `
        
        this.setupEventListeners()
        this.scrollToBottom()
    }

    renderMessagesHtml() {
        if (this.messages.length === 0) {
            return /* html */`
                <div class="chat-empty">
                    <p>${t('chat.startConversation')}</p>
                </div>
            `
        }
        
        return this.messages.map(msg => /* html */`
            <div class="chat-message ${msg.isOwn ? 'own' : 'other'}">
                <div class="message-bubble">
                    <p>${escapeHTML(msg.text)}</p>
                    <span class="message-time">${this.formatTime(msg.timestamp)}</span>
                </div>
            </div>
        `).join('')
    }

    renderMessages() {
        const container = this.querySelector('#chat-messages')
        if (container) {
            container.innerHTML = this.renderMessagesHtml()
        }
    }

    renderDealSection() {
        if (!this.conversation || !this.conversation.otherPublicKey) return ''

        if (!this.deal) {
            return /* html */`
                <div class="deal-section">
                    <button class="deal-btn" id="deal-create-btn">
                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                            <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
                            <circle cx="9" cy="7" r="4"></circle>
                            <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
                            <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
                        </svg>
                        ${t('reputation.confirmDeal')}
                    </button>
                </div>
            `
        }

        if (this.deal.status === 'pending') {
            const userHash = this._cachedUserHash
            const iAmConfirmed = (this.deal.seller_hash === userHash && this.deal.seller_confirmed)
                || (this.deal.buyer_hash === userHash && this.deal.buyer_confirmed)

            if (iAmConfirmed) {
                return /* html */`
                    <div class="deal-section">
                        <div class="deal-status deal-pending">
                            <span class="pulse-dot"></span>
                            ${t('reputation.dealPending')}
                        </div>
                    </div>
                `
            }
            return /* html */`
                <div class="deal-section">
                    <button class="deal-btn deal-confirm" id="deal-confirm-btn">
                        ${t('reputation.confirmDeal')}
                    </button>
                    <span class="deal-hint">${t('reputation.confirmDealHint')}</span>
                </div>
            `
        }

        if (this.deal.status === 'confirmed') {
            if (this.hasRated) {
                return /* html */`
                    <div class="deal-section">
                        <div class="deal-status deal-confirmed">
                            ✓ ${t('reputation.dealConfirmed')} · ${t('reputation.rated')}
                        </div>
                    </div>
                `
            }
            return /* html */`
                <div class="deal-section">
                    <div class="deal-status deal-confirmed">✓ ${t('reputation.dealConfirmed')}</div>
                    <div class="deal-rating" id="deal-rating">
                        <span class="rating-label">${t('reputation.rate')}</span>
                        <div class="rating-stars">
                            ${[1,2,3,4,5].map(s => `<button class="star-btn" data-score="${s}" aria-label="${s}">★</button>`).join('')}
                        </div>
                    </div>
                </div>
            `
        }

        return ''
    }

    setupEventListeners() {
        const keyAcceptBtn = this.querySelector('#key-accept-btn')
        keyAcceptBtn?.addEventListener('click', () => this.acceptKeyChange())

        const form = this.querySelector('#chat-form')
        form?.addEventListener('submit', (e) => this.handleSubmit(e))

        const dealCreateBtn = this.querySelector('#deal-create-btn')
        dealCreateBtn?.addEventListener('click', () => this.handleCreateDeal())

        const dealConfirmBtn = this.querySelector('#deal-confirm-btn')
        dealConfirmBtn?.addEventListener('click', () => this.handleConfirmDeal())

        this.querySelectorAll('.star-btn').forEach(btn => {
            btn.addEventListener('click', () => this.handleRate(parseInt(btn.dataset.score)))
        })
    }

    async handleSubmit(e) {
        e.preventDefault()
        
        const input = this.querySelector('#message-input')
        const text = input?.value.trim()
        
        if (!text || !this.conversation) return
        
        input.value = ''
        
        await conversationsService.sendMessage(
            this.conversation.id,
            this.conversation.otherPublicKey,
            text,
            'text',
            this.mySecretKey
        )
        
        await this.refreshMessages()
    }

    async handleCreateDeal() {
        if (!this.conversation) return
        try {
            this._cachedUserHash = await reputationService.getUserHash()
            this.deal = await reputationService.createDeal(this.conversation)
            this.render()
        } catch (e) {
            console.error('Failed to create deal:', e)
        }
    }

    async handleConfirmDeal() {
        if (!this.deal) return
        try {
            this.deal = await reputationService.confirmDeal(this.deal.id)
            this.render()
        } catch (e) {
            console.error('Failed to confirm deal:', e)
        }
    }

    async handleRate(score) {
        if (!this.deal) return
        try {
            await reputationService.rateDeal(this.deal.id, score)
            this.hasRated = true
            this.render()
        } catch (e) {
            console.error('Failed to rate:', e)
        }
    }

    scrollToBottom() {
        const container = this.querySelector('#chat-messages')
        if (container) {
            container.scrollTop = container.scrollHeight
        }
    }

    formatTime(timestamp) {
        const date = new Date(timestamp)
        return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
    }

}

customElements.define('chat-widget', ChatWidget)

const style = document.createElement('style')
style.textContent = /* css */`
    chat-widget {
        display: block;
    }
    
    chat-widget .chat-widget {
        display: flex;
        flex-direction: column;
        height: 400px;
        border: 1px solid var(--color-border);
        border-radius: var(--radius-lg);
        overflow: hidden;
        background: var(--color-bg);
    }
    
    chat-widget .chat-loading,
    chat-widget .chat-error {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        color: var(--color-text-muted);
        text-align: center;
        padding: var(--space-lg);
    }

    chat-widget .chat-key-warning {
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: var(--space-xl);
        text-align: center;
    }

    chat-widget .key-warning-icon {
        font-size: 2.5rem;
        margin-bottom: var(--space-md);
        filter: grayscale(1);
    }

    chat-widget .chat-key-warning h4 {
        margin: 0 0 var(--space-sm);
        color: var(--color-text);
    }

    chat-widget .chat-key-warning p {
        margin: 0 0 var(--space-lg);
        color: var(--color-text-muted);
        font-size: var(--font-size-sm);
        max-width: 300px;
    }

    chat-widget .key-warning-actions {
        display: flex;
        gap: var(--space-sm);
    }
    
    chat-widget .chat-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: var(--space-md);
        background: var(--color-bg-secondary);
        border-bottom: 1px solid var(--color-border);
    }
    
    chat-widget .chat-recipient {
        font-weight: var(--font-weight-medium);
        color: var(--color-text);
    }
    
    chat-widget .chat-encrypted {
        font-size: var(--font-size-sm);
        cursor: help;
        filter: grayscale(1);
    }
    
    chat-widget .chat-messages {
        flex: 1;
        overflow-y: auto;
        padding: var(--space-md);
        display: flex;
        flex-direction: column;
        gap: var(--space-sm);
    }
    
    chat-widget .chat-empty {
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        color: var(--color-text-muted);
        text-align: center;
    }
    
    chat-widget .chat-message {
        display: flex;
        max-width: 80%;
    }
    
    chat-widget .chat-message.own {
        align-self: flex-end;
    }
    
    chat-widget .chat-message.other {
        align-self: flex-start;
    }
    
    chat-widget .message-bubble {
        padding: var(--space-sm) var(--space-md);
        border-radius: var(--radius-lg);
        position: relative;
    }
    
    chat-widget .chat-message.own .message-bubble {
        background: var(--color-text);
        color: var(--color-bg);
        border-bottom-right-radius: var(--radius-sm);
    }
    
    chat-widget .chat-message.other .message-bubble {
        background: var(--color-bg-tertiary);
        color: var(--color-text);
        border-bottom-left-radius: var(--radius-sm);
    }
    
    chat-widget .message-bubble p {
        margin: 0;
        word-break: break-word;
    }
    
    chat-widget .message-time {
        display: block;
        font-size: var(--font-size-xs);
        opacity: 0.7;
        margin-top: var(--space-xs);
    }
    
    chat-widget .chat-input {
        display: flex;
        gap: var(--space-sm);
        padding: var(--space-md);
        border-top: 1px solid var(--color-border);
        background: var(--color-bg-secondary);
    }
    
    chat-widget .chat-input input {
        flex: 1;
        padding: var(--space-sm) var(--space-md);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        background: var(--color-bg);
        color: var(--color-text);
        font-size: var(--font-size-base);
    }
    
    chat-widget .chat-input input::placeholder {
        color: var(--color-text-muted);
    }
    
    chat-widget .chat-input input:focus {
        outline: none;
        border-color: var(--color-text-muted);
    }
    
    chat-widget .chat-input button {
        padding: var(--space-sm);
        border-radius: var(--radius-md);
        background: var(--color-text);
        color: var(--color-bg);
    }
    
    chat-widget .chat-input button:hover {
        background: var(--color-text-secondary);
    }
    
    chat-widget .deal-section {
        padding: var(--space-sm) var(--space-md);
        border-top: 1px solid var(--color-border);
        background: var(--color-bg-secondary);
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        flex-wrap: wrap;
    }

    chat-widget .deal-btn {
        display: inline-flex;
        align-items: center;
        gap: var(--space-xs);
        padding: var(--space-xs) var(--space-sm);
        border: 1px solid var(--color-border);
        border-radius: var(--radius-md);
        background: var(--color-bg);
        color: var(--color-text-secondary);
        font-size: var(--font-size-sm);
        cursor: pointer;
        transition: all 0.2s;
    }

    chat-widget .deal-btn:hover {
        border-color: var(--color-text-muted);
        color: var(--color-text);
    }

    chat-widget .deal-btn.deal-confirm {
        background: var(--color-text);
        color: var(--color-bg);
        border-color: var(--color-text);
    }

    chat-widget .deal-btn.deal-confirm:hover {
        opacity: 0.8;
    }

    chat-widget .deal-hint {
        font-size: var(--font-size-xs);
        color: var(--color-text-muted);
    }

    chat-widget .deal-status {
        font-size: var(--font-size-sm);
        display: flex;
        align-items: center;
        gap: var(--space-xs);
    }

    chat-widget .deal-pending {
        color: var(--color-text-muted);
    }

    chat-widget .deal-confirmed {
        color: var(--color-text-secondary);
    }

    chat-widget .deal-rating {
        display: flex;
        align-items: center;
        gap: var(--space-sm);
        margin-left: auto;
    }

    chat-widget .rating-label {
        font-size: var(--font-size-xs);
        color: var(--color-text-muted);
    }

    chat-widget .rating-stars {
        display: flex;
        gap: 2px;
    }

    chat-widget .star-btn {
        background: none;
        border: none;
        cursor: pointer;
        font-size: var(--font-size-lg);
        color: var(--color-border);
        padding: 0;
        line-height: 1;
        transition: color 0.15s;
    }

    chat-widget .star-btn:hover,
    chat-widget .star-btn:hover ~ .star-btn {
        color: var(--color-text-muted);
    }

    chat-widget .rating-stars:hover .star-btn {
        color: var(--color-text);
    }

    chat-widget .rating-stars .star-btn:hover ~ .star-btn {
        color: var(--color-border);
    }

    chat-widget .pulse-dot {
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: var(--color-text-muted);
        display: inline-block;
        animation: pulse-deal 1.5s infinite;
    }

    @keyframes pulse-deal {
        0%, 100% { opacity: 1; }
        50% { opacity: 0.3; }
    }
`
document.head.appendChild(style)

export { ChatWidget }
