// 数据同步功能实现

import { db } from './db'
import * as onlineBillApi from '../api/bill'
import * as onlineCategoryApi from '../api/category'
import * as onlineAccountApi from '../api/account'
import * as onlineBudgetApi from '../api/budget'

// 获取当前用户ID
function getCurrentUserId() {
  const userInfo = uni.getStorageSync('userInfo') || {}
  return userInfo.userId || 'local_user'
}

// 检查是否为离线用户
function isOfflineUser() {
  const userInfo = uni.getStorageSync('userInfo') || {}
  return userInfo.isOffline === true || userInfo.userId === 'local_user'
}

// 账单同步逻辑
const syncBills = async () => {
  if (isOfflineUser()) {
    throw new Error('离线用户无法同步数据')
  }
  
  const userId = getCurrentUserId()
  
  try {
    // 1. 获取本地未同步的账单
    const localBillsSql = `SELECT * FROM bill WHERE user_id = ? AND is_synced = 0`
    const localBills = await db.query(localBillsSql, [userId])
    
    // 2. 获取服务器端账单
    const serverBills = await onlineBillApi.getBills({ userId })
    
    // 3. 比较并同步数据
    for (const localBill of localBills) {
      // 检查服务器是否已有相同账单
      const existingBill = serverBills.find(bill => {
        return bill.amount === localBill.amount &&
               bill.type === localBill.type &&
               bill.bill_date === localBill.bill_date &&
               bill.description === localBill.description &&
               bill.category_id === localBill.category_id
      })
      
      if (existingBill) {
        // 已有相同账单，标记为已同步
        const updateSql = `UPDATE bill SET is_synced = 1 WHERE id = ?`
        await db.update(updateSql, [localBill.id])
      } else {
        // 没有相同账单，上传到服务器
        await onlineBillApi.createBill({
          categoryId: localBill.category_id,
          amount: localBill.amount,
          description: localBill.description,
          billDate: localBill.bill_date,
          type: localBill.type
        })
        
        // 标记为已同步
        const updateSql = `UPDATE bill SET is_synced = 1 WHERE id = ?`
        await db.update(updateSql, [localBill.id])
      }
    }
    
    // 4. 将服务器端数据同步到本地
    for (const serverBill of serverBills) {
      // 检查本地是否已有相同账单
      const checkSql = `SELECT * FROM bill WHERE user_id = ? AND amount = ? AND type = ? AND bill_date = ? AND description = ? AND category_id = ?`
      const existingBills = await db.query(checkSql, [
        userId,
        serverBill.amount,
        serverBill.type,
        serverBill.bill_date,
        serverBill.description,
        serverBill.category_id
      ])
      
      if (existingBills.length === 0) {
        // 本地没有相同账单，添加到本地
        const insertSql = `INSERT INTO bill (user_id, category_id, amount, description, bill_date, type, is_synced) 
                          VALUES (?, ?, ?, ?, ?, ?, 1)`
        await db.update(insertSql, [
          userId,
          serverBill.category_id,
          serverBill.amount,
          serverBill.description,
          serverBill.bill_date,
          serverBill.type
        ])
      }
    }
    
    return { success: true, message: '账单同步成功', syncedCount: localBills.length }
  } catch (error) {
    console.error('同步账单失败:', error)
    throw error
  }
}

// 分类同步逻辑
const syncCategories = async () => {
  if (isOfflineUser()) {
    throw new Error('离线用户无法同步数据')
  }
  
  const userId = getCurrentUserId()
  
  try {
    // 1. 获取本地用户自定义分类
    const localCategoriesSql = `SELECT * FROM category WHERE user_id = ?`
    const localCategories = await db.query(localCategoriesSql, [userId])
    
    // 2. 获取服务器端分类
    const serverCategories = await onlineCategoryApi.getCategories({ userId })
    
    // 3. 比较并同步数据
    for (const localCategory of localCategories) {
      // 检查服务器是否已有相同分类
      const existingCategory = serverCategories.find(category => {
        return category.name === localCategory.name &&
               category.type === localCategory.type
      })
      
      if (!existingCategory) {
        // 没有相同分类，上传到服务器
        await onlineCategoryApi.createCategory({
          name: localCategory.name,
          icon: localCategory.icon,
          type: localCategory.type,
          sortOrder: localCategory.sort_order
        })
      }
    }
    
    // 4. 将服务器端分类同步到本地
    for (const serverCategory of serverCategories) {
      // 检查本地是否已有相同分类
      const checkSql = `SELECT * FROM category WHERE user_id = ? AND name = ? AND type = ?`
      const existingCategories = await db.query(checkSql, [
        userId,
        serverCategory.name,
        serverCategory.type
      ])
      
      if (existingCategories.length === 0) {
        // 本地没有相同分类，添加到本地
        const insertSql = `INSERT INTO category (user_id, name, icon, type, sort_order) 
                          VALUES (?, ?, ?, ?, ?)`
        await db.update(insertSql, [
          userId,
          serverCategory.name,
          serverCategory.icon,
          serverCategory.type,
          serverCategory.sort_order
        ])
      }
    }
    
    return { success: true, message: '分类同步成功' }
  } catch (error) {
    console.error('同步分类失败:', error)
    throw error
  }
}

// 账户同步逻辑
const syncAccount = async () => {
  if (isOfflineUser()) {
    throw new Error('离线用户无法同步数据')
  }
  
  const userId = getCurrentUserId()
  
  try {
    // 1. 获取本地账户信息
    const localAccountSql = `SELECT * FROM account WHERE user_id = ?`
    const localAccounts = await db.query(localAccountSql, [userId])
    
    if (localAccounts.length === 0) {
      return { success: true, message: '本地没有账户信息需要同步' }
    }
    
    const localAccount = localAccounts[0]
    
    // 2. 获取服务器端账户信息
    const serverAccount = await onlineAccountApi.getAccount({ userId })
    
    // 3. 比较并同步数据
    if (serverAccount) {
      // 服务器有账户信息，比较并更新
      if (localAccount.name !== serverAccount.name || localAccount.initial_balance !== serverAccount.initial_balance) {
        // 本地与服务器信息不一致，更新服务器端
        await onlineAccountApi.updateAccount({
          name: localAccount.name,
          initialBalance: localAccount.initial_balance
        })
      }
    } else {
      // 服务器没有账户信息，创建新账户
      await onlineAccountApi.updateAccount({
        name: localAccount.name,
        initialBalance: localAccount.initial_balance
      })
    }
    
    // 4. 将服务器端账户信息同步到本地
    const updatedServerAccount = await onlineAccountApi.getAccount({ userId })
    const updateSql = `UPDATE account SET name = ?, initial_balance = ? WHERE user_id = ?`
    await db.update(updateSql, [
      updatedServerAccount.name,
      updatedServerAccount.initial_balance,
      userId
    ])
    
    return { success: true, message: '账户同步成功' }
  } catch (error) {
    console.error('同步账户失败:', error)
    throw error
  }
}

// 预算同步逻辑
const syncBudgets = async () => {
  if (isOfflineUser()) {
    throw new Error('离线用户无法同步数据')
  }
  
  const userId = getCurrentUserId()
  
  try {
    // 1. 获取本地预算
    const localBudgetsSql = `SELECT * FROM budget WHERE user_id = ?`
    const localBudgets = await db.query(localBudgetsSql, [userId])
    
    // 2. 获取服务器端预算
    const serverBudget = await onlineBudgetApi.getBudget({ userId })
    
    // 3. 比较并同步数据
    for (const localBudget of localBudgets) {
      // 检查服务器是否已有相同月份预算
      const checkSql = `SELECT * FROM budget WHERE user_id = ? AND year = ? AND month = ?`
      const existingBudgets = await db.query(checkSql, [
        userId,
        localBudget.year,
        localBudget.month
      ])
      
      if (existingBudgets.length === 0) {
        // 没有相同月份预算，上传到服务器
        await onlineBudgetApi.setBudget({
          userId,
          year: localBudget.year,
          month: localBudget.month,
          amount: localBudget.amount
        })
      } else if (existingBudgets[0].amount !== localBudget.amount) {
        // 预算金额不一致，更新服务器
        await onlineBudgetApi.setBudget({
          userId,
          year: localBudget.year,
          month: localBudget.month,
          amount: localBudget.amount
        })
      }
    }
    
    // 4. 将服务器端预算同步到本地
    if (serverBudget) {
      // 检查本地是否已有相同月份预算
      const checkSql = `SELECT * FROM budget WHERE user_id = ? AND year = ? AND month = ?`
      const existingBudgets = await db.query(checkSql, [
        userId,
        serverBudget.year,
        serverBudget.month
      ])
      
      if (existingBudgets.length === 0) {
        // 本地没有相同月份预算，添加到本地
        const insertSql = `INSERT INTO budget (user_id, year, month, amount, is_synced) 
                          VALUES (?, ?, ?, ?, 1)`
        await db.update(insertSql, [
          userId,
          serverBudget.year,
          serverBudget.month,
          serverBudget.amount
        ])
      } else if (existingBudgets[0].amount !== serverBudget.amount) {
        // 预算金额不一致，更新本地
        const updateSql = `UPDATE budget SET amount = ?, is_synced = 1 WHERE user_id = ? AND year = ? AND month = ?`
        await db.update(updateSql, [
          serverBudget.amount,
          userId,
          serverBudget.year,
          serverBudget.month
        ])
      }
    }
    
    return { success: true, message: '预算同步成功' }
  } catch (error) {
    console.error('同步预算失败:', error)
    throw error
  }
}

// 全量同步数据
const syncAllData = async () => {
  if (isOfflineUser()) {
    throw new Error('离线用户无法同步数据')
  }
  
  try {
    // 1. 同步账单
    const billResult = await syncBills()
    
    // 2. 同步分类
    const categoryResult = await syncCategories()
    
    // 3. 同步账户
    const accountResult = await syncAccount()
    
    // 4. 同步预算
    const budgetResult = await syncBudgets()
    
    return {
      success: true,
      message: '数据同步成功',
      details: {
        bills: billResult,
        categories: categoryResult,
        account: accountResult,
        budgets: budgetResult
      }
    }
  } catch (error) {
    console.error('全量同步失败:', error)
    throw error
  }
}

// 数据同步模块导出
export const sync = {
  // 全量同步
  syncAll: syncAllData,
  
  // 账单同步
  syncBills,
  
  // 分类同步
  syncCategories,
  
  // 账户同步
  syncAccount,
  
  // 预算同步
  syncBudgets,
  
  // 检查同步状态
  checkSyncStatus: () => {
    const userInfo = uni.getStorageSync('userInfo') || {}
    const lastSyncTime = uni.getStorageSync('lastSyncTime') || null
    
    return {
      isOffline: userInfo.isOffline === true || userInfo.userId === 'local_user',
      lastSyncTime
    }
  }
}

export default sync
