import { NextRequest, NextResponse } from 'next/server'
import bcrypt from 'bcryptjs'
import { getDb } from '@/server/db'
import { pickRowString, readDisplayName, readUserId } from '@/server/pgRow'
import { USER_AUTH_SQL, USER_LOGIN_HISTORY_SQL } from '@/server/userAuthSql'
import { setUserSession } from '../../_helpers/session'
import { generateSessionId, generateLoginHistoryId } from '../../_helpers/generateSessionId'

export const runtime = 'nodejs'

function json(data: unknown, init?: ResponseInit) {
    return NextResponse.json(data, init)
}

/**
 * 解析 User-Agent 取得裝置資訊
 */
function parseUserAgent(userAgent: string): { deviceType: string; deviceName: string } {
    const ua = userAgent.toLowerCase()
    let deviceType = 'Unknown'
    if (ua.includes('mobile') || ua.includes('android') || ua.includes('iphone') || ua.includes('ipad')) {
        deviceType = 'Mobile'
    } else if (ua.includes('tablet')) {
        deviceType = 'Tablet'
    } else {
        deviceType = 'Desktop'
    }
    let deviceName = 'Unknown'
    if (ua.includes('edg/')) {
        deviceName = 'Microsoft Edge'
    } else if (ua.includes('chrome/') && !ua.includes('edg/')) {
        deviceName = 'Google Chrome'
    } else if (ua.includes('firefox/')) {
        deviceName = 'Mozilla Firefox'
    } else if (ua.includes('safari/') && !ua.includes('chrome/')) {
        deviceName = 'Safari'
    } else if (ua.includes('opera/') || ua.includes('opr/')) {
        deviceName = 'Opera'
    } else {
        deviceName = 'Unknown Browser'
    }
    return { deviceType, deviceName }
}

/**
 * 取得客戶端 IP 地址
 */
function getClientIp(request: NextRequest): string {
    const forwarded = request.headers.get('x-forwarded-for')
    const realIp = request.headers.get('x-real-ip')
    const remoteAddr = request.headers.get('remote-addr')

    if (forwarded) {
        return forwarded.split(',')[0].trim()
    }
    if (realIp) {
        return realIp
    }
    if (remoteAddr) {
        return remoteAddr
    }
    return '0.0.0.0'
}

export async function POST(req: NextRequest) {
    try {
        const body = await req.json().catch(() => ({}))
        const account = String(body?.account ?? '').trim()
        const password = String(body?.password ?? '').trim()
        if (!account || account.length < 6 || account.length > 12) {
            return json({ ok: false, error: 'INVALID_ACCOUNT' }, { status: 400 })
        }
        if (!password || password.length < 10 || password.length > 15) {
            return json({ ok: false, error: 'INVALID_PASSWORD_LENGTH' }, { status: 400 })
        }
        const db = await getDb()
        const row = await db.get<Record<string, unknown>>(
            `SELECT user_id AS id, display_name AS displayName, COALESCE(email, '') AS email, password_hash AS passwordHash
             FROM users
             WHERE account = ?`,
            [account]
        )
        if (!row) {
            return json({ ok: false, error: 'USER_NOT_FOUND' }, { status: 401 })
        }
        const userId = readUserId(row)
        const displayName = readDisplayName(row) || account
        const email = pickRowString(row, 'email')
        const passwordHash = pickRowString(row, 'passwordHash', 'password_hash')
        if (!userId) {
            return json({ ok: false, error: 'USER_NOT_FOUND' }, { status: 401 })
        }
        if (!passwordHash) {
            return json({ ok: false, error: 'NO_PASSWORD' }, { status: 401 })
        }
        const passwordMatch = await bcrypt.compare(password, passwordHash)
        if (!passwordMatch) {
            return json({ ok: false, error: 'WRONG_CREDENTIALS' }, { status: 401 })
        }
        const userAgent = req.headers.get('user-agent') || 'Unknown'
        const ipAddress = getClientIp(req)
        const { deviceType, deviceName } = parseUserAgent(userAgent)
        const sessionId = generateSessionId()
        const loginHistoryId = generateLoginHistoryId()
        const nowSec = Math.floor(Date.now() / 1000)
        await db.run(USER_LOGIN_HISTORY_SQL.insert, [
            loginHistoryId,
            userId,
            ipAddress,
            null,
            userAgent,
            deviceType,
            deviceName,
            nowSec,
            nowSec,
        ])
        await db.run(USER_AUTH_SQL.insertSession, [
            sessionId,
            userId,
            userAgent,
            deviceType,
            deviceName,
            nowSec,
            nowSec,
        ])
        setUserSession(userId, sessionId)
        const response = json({
            ok: true,
            data: {
                userId,
                displayName,
                email,
            },
        })
        return response
    } catch (error) {
        console.error('Login error:', error)
        return json({ ok: false, error: 'INTERNAL_ERROR' }, { status: 500 })
    }
}

