import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class DatabaseHelper {
  static const _databaseVersion = 37;
  static final DatabaseHelper _instance = DatabaseHelper._internal();
  static Database? _database;

  factory DatabaseHelper() => _instance;

  DatabaseHelper._internal();

  Future<Database> get database async {
    if (_database != null) return _database!;
    _database = await _initDatabase();
    return _database!;
  }

  Future<Database> _initDatabase() async {
    String path = join(await getDatabasesPath(), 'gemi_invoice.db');
    return await openDatabase(
      path,
      version: _databaseVersion,
      onCreate: _onCreate,
      onUpgrade: _onUpgrade,
    );
  }

  Future<void> _onUpgrade(Database db, int oldVersion, int newVersion) async {
    if (oldVersion < 2) {
      await db.execute('ALTER TABLE invoices ADD COLUMN tax_rate REAL DEFAULT 0.10');
    }
    if (oldVersion < 3) {
      await db.execute('''
        CREATE TABLE company_info (
          id INTEGER PRIMARY KEY,
          name TEXT NOT NULL,
          zip_code TEXT,
          address TEXT,
          tel TEXT,
          fax TEXT,
          email TEXT,
          url TEXT,
          default_tax_rate REAL DEFAULT 0.10,
          seal_path TEXT
        )
      ''');
    }
    if (oldVersion < 4) {
      await db.execute('ALTER TABLE products ADD COLUMN barcode TEXT');
    }
    if (oldVersion < 5) {
      await db.execute('ALTER TABLE invoices ADD COLUMN customer_formal_name TEXT');
    }
    if (oldVersion < 6) {
      await db.execute('ALTER TABLE products ADD COLUMN category TEXT');
      await db.execute('CREATE INDEX idx_products_name ON products(name)');
      await db.execute('CREATE INDEX idx_products_barcode ON products(barcode)');
      await db.execute('''
        CREATE TABLE activity_logs (
          id TEXT PRIMARY KEY,
          action TEXT NOT NULL,
          target_type TEXT NOT NULL,
          target_id TEXT,
          details TEXT,
          timestamp TEXT NOT NULL
        )
      ''');
    }
    if (oldVersion < 7) {
      await db.execute('ALTER TABLE products ADD COLUMN stock_quantity INTEGER DEFAULT 0');
      await db.execute('ALTER TABLE invoices ADD COLUMN document_type TEXT DEFAULT "invoice"');
      await db.execute('ALTER TABLE invoice_items ADD COLUMN product_id TEXT');
    }
    if (oldVersion < 8) {
      await db.execute('ALTER TABLE invoices ADD COLUMN latitude REAL');
      await db.execute('ALTER TABLE invoices ADD COLUMN longitude REAL');
      await db.execute('''
        CREATE TABLE app_gps_history (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          latitude REAL NOT NULL,
          longitude REAL NOT NULL,
          timestamp TEXT NOT NULL
        )
      ''');
    }
    if (oldVersion < 9) {
      await db.execute('ALTER TABLE company_info ADD COLUMN tax_display_mode TEXT DEFAULT "normal"');
    }
    if (oldVersion < 10) {
      await db.execute('ALTER TABLE invoices ADD COLUMN terminal_id TEXT DEFAULT "T1"');
      await db.execute('ALTER TABLE invoices ADD COLUMN content_hash TEXT');
    }
    if (oldVersion < 11) {
      await db.execute('ALTER TABLE invoices ADD COLUMN is_draft INTEGER DEFAULT 0');
    }
    if (oldVersion < 12) {
      await db.execute('ALTER TABLE invoices ADD COLUMN subject TEXT');
    }
    if (oldVersion < 13) {
      await db.execute('ALTER TABLE company_info ADD COLUMN registration_number TEXT');
    }
    if (oldVersion < 14) {
      await _safeAddColumn(db, 'invoices', 'subject TEXT');
    }
    if (oldVersion < 15) {
      await _safeAddColumn(db, 'invoices', 'is_locked INTEGER DEFAULT 0');
      await _safeAddColumn(db, 'customers', 'is_locked INTEGER DEFAULT 0');
      await _safeAddColumn(db, 'products', 'is_locked INTEGER DEFAULT 0');
    }
    if (oldVersion < 16) {
      await db.execute('''
        CREATE TABLE customer_contacts (
          id TEXT PRIMARY KEY,
          customer_id TEXT NOT NULL,
          email TEXT,
          tel TEXT,
          address TEXT,
          version INTEGER NOT NULL,
          is_active INTEGER DEFAULT 1,
          created_at TEXT NOT NULL,
          FOREIGN KEY(customer_id) REFERENCES customers(id) ON DELETE CASCADE
        )
      ''');
      await db.execute('CREATE INDEX idx_customer_contacts_cust ON customer_contacts(customer_id)');

      // 既存顧客の連絡先を初期バージョンとしてコピー
      final existing = await db.query('customers');
      final now = DateTime.now().toIso8601String();
      for (final row in existing) {
        final contactId = "${row['id']}_v1";
        await db.insert('customer_contacts', {
          'id': contactId,
          'customer_id': row['id'],
          'email': null,
          'tel': row['tel'],
          'address': row['address'],
          'version': 1,
          'is_active': 1,
          'created_at': now,
        });
      }
    }
    if (oldVersion < 17) {
      await _safeAddColumn(db, 'invoices', 'contact_version_id INTEGER');
      await _safeAddColumn(db, 'invoices', 'contact_email_snapshot TEXT');
      await _safeAddColumn(db, 'invoices', 'contact_tel_snapshot TEXT');
      await _safeAddColumn(db, 'invoices', 'contact_address_snapshot TEXT');
    }
    if (oldVersion < 20) {
      await _safeAddColumn(db, 'company_info', 'fax TEXT');
      await _safeAddColumn(db, 'company_info', 'email TEXT');
      await _safeAddColumn(db, 'company_info', 'url TEXT');
    }
    if (oldVersion < 18) {
      await _safeAddColumn(db, 'customers', 'contact_version_id INTEGER');
    }
    if (oldVersion < 19) {
      await _safeAddColumn(db, 'customers', 'head_char1 TEXT');
      await _safeAddColumn(db, 'customers', 'head_char2 TEXT');
      await db.execute('CREATE INDEX IF NOT EXISTS idx_customers_head1 ON customers(head_char1)');
      await db.execute('CREATE INDEX IF NOT EXISTS idx_customers_head2 ON customers(head_char2)');
    }
    if (oldVersion < 20) {
      await _safeAddColumn(db, 'customers', 'email TEXT');
    }
    if (oldVersion < 22) {
      await db.execute('''
        CREATE TABLE IF NOT EXISTS app_settings (
          key TEXT PRIMARY KEY,
          value TEXT
        )
      ''');
    }
    if (oldVersion < 23) {
      await _safeAddColumn(db, 'customers', 'is_hidden INTEGER DEFAULT 0');
      await _safeAddColumn(db, 'products', 'is_hidden INTEGER DEFAULT 0');
      await db.execute('CREATE INDEX IF NOT EXISTS idx_customers_hidden ON customers(is_hidden)');
      await db.execute('CREATE INDEX IF NOT EXISTS idx_products_hidden ON products(is_hidden)');
    }
    if (oldVersion < 24) {
      await db.execute('''
        CREATE TABLE IF NOT EXISTS master_hidden (
          master_type TEXT NOT NULL,
          master_id TEXT NOT NULL,
          is_hidden INTEGER DEFAULT 0,
          PRIMARY KEY(master_type, master_id)
        )
      ''');
      await db.execute('CREATE INDEX IF NOT EXISTS idx_master_hidden_type ON master_hidden(master_type)');
    }
    if (oldVersion < 25) {
      await _safeAddColumn(db, 'invoices', 'company_snapshot TEXT');
      await _safeAddColumn(db, 'invoices', 'company_seal_hash TEXT');
      await _safeAddColumn(db, 'invoices', 'meta_json TEXT');
      await _safeAddColumn(db, 'invoices', 'meta_hash TEXT');
    }
    if (oldVersion < 26) {
      await db.execute('''
        CREATE TABLE IF NOT EXISTS chat_messages (
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          message_id TEXT UNIQUE NOT NULL,
          client_id TEXT NOT NULL,
          direction TEXT NOT NULL,
          body TEXT NOT NULL,
          created_at INTEGER NOT NULL,
          synced INTEGER DEFAULT 0,
          delivered_at INTEGER
        )
      ''');
      await db.execute('CREATE INDEX IF NOT EXISTS idx_chat_messages_created_at ON chat_messages(created_at)');
    }
    if (oldVersion < 27) {
      await _createSalesOrderTables(db);
    }
    if (oldVersion < 28) {
      await _createShipmentTables(db);
    }
    if (oldVersion < 29) {
      await _createInventoryTables(db);
    }
    if (oldVersion < 30) {
      await _createReceivableTables(db);
    }
    if (oldVersion < 31) {
      await _safeAddColumn(db, 'invoices', 'previous_chain_hash TEXT');
      await _safeAddColumn(db, 'invoices', 'chain_hash TEXT');
      await _safeAddColumn(db, 'invoices', "chain_status TEXT DEFAULT 'pending'");
    }
    if (oldVersion < 32) {
      await _createSupplierTables(db);
      await _createDepartmentTables(db);
      await _createStaffTables(db);
      await _createTaxSettingsTable(db);
    }
    if (oldVersion < 33) {
      await _safeAddColumn(db, 'shipments', 'tracking_url TEXT');
      await _safeAddColumn(db, 'shipments', 'label_pdf_path TEXT');
    }
    if (oldVersion < 34) {
      await _createSalesEntryTables(db);
    }
    if (oldVersion < 35) {
      await _safeAddColumn(db, 'products', 'wholesale_price INTEGER DEFAULT 0');
      await _safeAddColumn(db, 'sales_line_items', 'cost_amount INTEGER DEFAULT 0');
      await _safeAddColumn(db, 'sales_line_items', 'cost_is_provisional INTEGER DEFAULT 0');
    }
    if (oldVersion < 36) {
      await _safeAddColumn(db, 'sales_entries', 'settlement_method TEXT');
      await _safeAddColumn(db, 'sales_entries', 'settlement_card_company TEXT');
      await _safeAddColumn(db, 'sales_entries', 'settlement_due_date TEXT');
    }
    if (oldVersion < 37) {
      await _createPurchaseEntryTables(db);
    }
  }

  Future<void> _onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE customers (
        id TEXT PRIMARY KEY,
        display_name TEXT NOT NULL,
        formal_name TEXT NOT NULL,
        title TEXT DEFAULT '様',
        department TEXT,
        address TEXT,
        tel TEXT,
        email TEXT,
        contact_version_id INTEGER,
        odoo_id TEXT,
        head_char1 TEXT,
        head_char2 TEXT,
        is_locked INTEGER DEFAULT 0,
        is_hidden INTEGER DEFAULT 0,
        is_synced INTEGER DEFAULT 0,
        updated_at TEXT NOT NULL
      )
    ''');

    await db.execute('''
      CREATE TABLE customer_gps_history (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        customer_id TEXT NOT NULL,
        latitude REAL NOT NULL,
        longitude REAL NOT NULL,
        timestamp TEXT NOT NULL,
        FOREIGN KEY (customer_id) REFERENCES customers (id) ON DELETE CASCADE
      )
    ''');

    await db.execute('''
      CREATE TABLE customer_contacts (
        id TEXT PRIMARY KEY,
        customer_id TEXT NOT NULL,
        email TEXT,
        tel TEXT,
        address TEXT,
        version INTEGER NOT NULL,
        is_active INTEGER DEFAULT 1,
        created_at TEXT NOT NULL,
        FOREIGN KEY(customer_id) REFERENCES customers(id) ON DELETE CASCADE
      )
    ''');
    await db.execute('CREATE INDEX idx_customer_contacts_cust ON customer_contacts(customer_id)');

    // 商品マスター
    await db.execute('''
      CREATE TABLE products (
        id TEXT PRIMARY KEY,
        name TEXT NOT NULL,
        default_unit_price INTEGER,
        wholesale_price INTEGER DEFAULT 0,
        barcode TEXT,
        category TEXT,
        stock_quantity INTEGER DEFAULT 0,
        is_locked INTEGER DEFAULT 0,
        is_hidden INTEGER DEFAULT 0,
        odoo_id TEXT
      )
    ''');
    await db.execute('CREATE INDEX idx_products_name ON products(name)');
    await db.execute('CREATE INDEX idx_products_barcode ON products(barcode)');

    await db.execute('''
      CREATE TABLE master_hidden (
        master_type TEXT NOT NULL,
        master_id TEXT NOT NULL,
        is_hidden INTEGER DEFAULT 0,
        PRIMARY KEY(master_type, master_id)
      )
    ''');
    await db.execute('CREATE INDEX idx_master_hidden_type ON master_hidden(master_type)');

    await _createSupplierTables(db);
    await _createDepartmentTables(db);
    await _createStaffTables(db);
    await _createTaxSettingsTable(db);

    // 伝票マスター
    await db.execute('''
      CREATE TABLE invoices (
        id TEXT PRIMARY KEY,
        customer_id TEXT NOT NULL,
        date TEXT NOT NULL,
        notes TEXT,
        subject TEXT,
        file_path TEXT,
        total_amount INTEGER,
        tax_rate REAL DEFAULT 0.10,
        document_type TEXT DEFAULT "invoice",
        customer_formal_name TEXT,
        odoo_id TEXT,
        is_synced INTEGER DEFAULT 0,
        updated_at TEXT NOT NULL,
        latitude REAL,
        longitude REAL,
        terminal_id TEXT DEFAULT "T1",
        content_hash TEXT,
        is_draft INTEGER DEFAULT 0,
        is_locked INTEGER DEFAULT 0,
        contact_version_id INTEGER,
        contact_email_snapshot TEXT,
        contact_tel_snapshot TEXT,
        contact_address_snapshot TEXT,
        company_snapshot TEXT,
        company_seal_hash TEXT,
        meta_json TEXT,
        meta_hash TEXT,
        FOREIGN KEY (customer_id) REFERENCES customers (id)
      )
    ''');

    await db.execute('''
      CREATE TABLE app_gps_history (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        latitude REAL NOT NULL,
        longitude REAL NOT NULL,
        timestamp TEXT NOT NULL
      )
    ''');

    // 伝票明細
    await db.execute('''
      CREATE TABLE invoice_items (
        id TEXT PRIMARY KEY,
        invoice_id TEXT NOT NULL,
        product_id TEXT,
        description TEXT NOT NULL,
        quantity INTEGER NOT NULL,
        unit_price INTEGER NOT NULL,
        FOREIGN KEY (invoice_id) REFERENCES invoices (id) ON DELETE CASCADE
      )
    ''');

    await db.execute('''
      CREATE TABLE company_info (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL,
        zip_code TEXT,
        address TEXT,
        tel TEXT,
        default_tax_rate REAL DEFAULT 0.10,
        seal_path TEXT,
        tax_display_mode TEXT DEFAULT "normal",
        registration_number TEXT
      )
    ''');

    await db.execute('''
      CREATE TABLE activity_logs (
        id TEXT PRIMARY KEY,
        action TEXT NOT NULL,
        target_type TEXT NOT NULL,
        target_id TEXT,
        details TEXT,
        timestamp TEXT NOT NULL
      )
    ''');

    await db.execute('''
      CREATE TABLE app_settings (
        key TEXT PRIMARY KEY,
        value TEXT
      )
    ''');

    await db.execute('''
      CREATE TABLE chat_messages (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        message_id TEXT UNIQUE NOT NULL,
        client_id TEXT NOT NULL,
        direction TEXT NOT NULL,
        body TEXT NOT NULL,
        created_at INTEGER NOT NULL,
        synced INTEGER DEFAULT 0,
        delivered_at INTEGER
      )
    ''');
    await db.execute('CREATE INDEX idx_chat_messages_created_at ON chat_messages(created_at)');
    await _createSalesOrderTables(db);
    await _createShipmentTables(db);
    await _createInventoryTables(db);
    await _createReceivableTables(db);
    await _createSalesEntryTables(db);
    await _createPurchaseEntryTables(db);
    await _safeAddColumn(db, 'invoices', 'previous_chain_hash TEXT');
    await _safeAddColumn(db, 'invoices', 'chain_hash TEXT');
    await _safeAddColumn(db, 'invoices', "chain_status TEXT DEFAULT 'pending'");
  }

  Future<void> _safeAddColumn(Database db, String table, String columnDef) async {
    try {
      await db.execute('ALTER TABLE $table ADD COLUMN $columnDef');
    } catch (_) {
      // Ignore if the column already exists.
    }
  }

  Future<void> _createSalesOrderTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS sales_orders (
        id TEXT PRIMARY KEY,
        order_number TEXT,
        customer_id TEXT NOT NULL,
        customer_name_snapshot TEXT,
        order_date TEXT NOT NULL,
        requested_ship_date TEXT,
        status TEXT NOT NULL,
        subtotal INTEGER DEFAULT 0,
        tax_amount INTEGER DEFAULT 0,
        total_amount INTEGER DEFAULT 0,
        notes TEXT,
        assigned_to TEXT,
        workflow_stage TEXT,
        created_at TEXT NOT NULL,
        updated_at TEXT NOT NULL,
        FOREIGN KEY(customer_id) REFERENCES customers(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_sales_orders_customer ON sales_orders(customer_id)');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_sales_orders_status ON sales_orders(status)');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_sales_orders_date ON sales_orders(order_date)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS sales_order_items (
        id TEXT PRIMARY KEY,
        order_id TEXT NOT NULL,
        product_id TEXT,
        description TEXT NOT NULL,
        quantity INTEGER NOT NULL,
        unit_price INTEGER NOT NULL,
        tax_rate REAL DEFAULT 0,
        sort_index INTEGER DEFAULT 0,
        FOREIGN KEY(order_id) REFERENCES sales_orders(id) ON DELETE CASCADE
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_sales_order_items_order ON sales_order_items(order_id)');
  }

  Future<void> _createShipmentTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS shipments (
        id TEXT PRIMARY KEY,
        order_id TEXT,
        order_number_snapshot TEXT,
        customer_name_snapshot TEXT,
        scheduled_ship_date TEXT,
        actual_ship_date TEXT,
        status TEXT NOT NULL,
        carrier_name TEXT,
        tracking_number TEXT,
        tracking_url TEXT,
        label_pdf_path TEXT,
        notes TEXT,
        picking_completed_at TEXT,
        created_at TEXT NOT NULL,
        updated_at TEXT NOT NULL,
        FOREIGN KEY(order_id) REFERENCES sales_orders(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_shipments_status ON shipments(status)');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_shipments_order ON shipments(order_id)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS shipment_items (
        id TEXT PRIMARY KEY,
        shipment_id TEXT NOT NULL,
        order_item_id TEXT,
        description TEXT NOT NULL,
        quantity INTEGER NOT NULL,
        FOREIGN KEY(shipment_id) REFERENCES shipments(id) ON DELETE CASCADE,
        FOREIGN KEY(order_item_id) REFERENCES sales_order_items(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_shipment_items_shipment ON shipment_items(shipment_id)');
  }

  Future<void> _createInventoryTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS inventory_movements (
        id TEXT PRIMARY KEY,
        product_id TEXT NOT NULL,
        product_name_snapshot TEXT,
        movement_type TEXT NOT NULL,
        quantity INTEGER NOT NULL,
        quantity_delta INTEGER NOT NULL,
        reference TEXT,
        notes TEXT,
        created_at TEXT NOT NULL,
        FOREIGN KEY(product_id) REFERENCES products(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_inventory_movements_product ON inventory_movements(product_id)');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_inventory_movements_created ON inventory_movements(created_at)');
  }

  Future<void> _createReceivableTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS receivable_payments (
        id TEXT PRIMARY KEY,
        invoice_id TEXT NOT NULL,
        amount INTEGER NOT NULL,
        payment_date TEXT NOT NULL,
        method TEXT NOT NULL,
        notes TEXT,
        created_at TEXT NOT NULL,
        FOREIGN KEY(invoice_id) REFERENCES invoices(id) ON DELETE CASCADE
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_receivable_payments_invoice ON receivable_payments(invoice_id)');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_receivable_payments_date ON receivable_payments(payment_date)');
  }

  Future<void> _createSupplierTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS suppliers (
        id TEXT PRIMARY KEY,
        name TEXT NOT NULL,
        contact_person TEXT,
        email TEXT,
        tel TEXT,
        address TEXT,
        closing_day INTEGER,
        payment_site_days INTEGER DEFAULT 30,
        notes TEXT,
        is_hidden INTEGER DEFAULT 0,
        updated_at TEXT NOT NULL
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_suppliers_name ON suppliers(name)');
  }

  Future<void> _createDepartmentTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS departments (
        id TEXT PRIMARY KEY,
        name TEXT NOT NULL,
        code TEXT,
        description TEXT,
        is_active INTEGER DEFAULT 1,
        updated_at TEXT NOT NULL
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_departments_name ON departments(name)');
  }

  Future<void> _createStaffTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS staff_members (
        id TEXT PRIMARY KEY,
        name TEXT NOT NULL,
        email TEXT,
        tel TEXT,
        role TEXT,
        department_id TEXT,
        permission_level TEXT,
        is_active INTEGER DEFAULT 1,
        updated_at TEXT NOT NULL,
        FOREIGN KEY(department_id) REFERENCES departments(id) ON DELETE SET NULL
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_staff_department ON staff_members(department_id)');
  }

  Future<void> _createTaxSettingsTable(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS tax_settings (
        id TEXT PRIMARY KEY,
        rate REAL NOT NULL,
        rounding_mode TEXT NOT NULL,
        updated_at TEXT NOT NULL
      )
    ''');
    final existing = await db.query('tax_settings', limit: 1);
    if (existing.isEmpty) {
      await db.insert('tax_settings', {
        'id': 'default',
        'rate': 0.1,
        'rounding_mode': 'round',
        'updated_at': DateTime.now().toIso8601String(),
      });
    }
  }

  Future<void> _createSalesEntryTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS sales_entries (
        id TEXT PRIMARY KEY,
        customer_id TEXT,
        customer_name_snapshot TEXT,
        subject TEXT,
        issue_date TEXT NOT NULL,
        status TEXT NOT NULL,
        amount_tax_excl INTEGER DEFAULT 0,
        tax_amount INTEGER DEFAULT 0,
        amount_tax_incl INTEGER DEFAULT 0,
        notes TEXT,
        settlement_method TEXT,
        settlement_card_company TEXT,
        settlement_due_date TEXT,
        created_at TEXT NOT NULL,
        updated_at TEXT NOT NULL,
        FOREIGN KEY(customer_id) REFERENCES customers(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_sales_entries_date ON sales_entries(issue_date)');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_sales_entries_status ON sales_entries(status)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS sales_line_items (
        id TEXT PRIMARY KEY,
        sales_entry_id TEXT NOT NULL,
        product_id TEXT,
        description TEXT NOT NULL,
        quantity INTEGER NOT NULL,
        unit_price INTEGER NOT NULL,
        tax_rate REAL DEFAULT 0,
        line_total INTEGER NOT NULL,
        cost_amount INTEGER DEFAULT 0,
        cost_is_provisional INTEGER DEFAULT 0,
        source_invoice_id TEXT,
        source_invoice_item_id TEXT,
        FOREIGN KEY(sales_entry_id) REFERENCES sales_entries(id) ON DELETE CASCADE
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_sales_line_items_entry ON sales_line_items(sales_entry_id)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS sales_entry_sources (
        id TEXT PRIMARY KEY,
        sales_entry_id TEXT NOT NULL,
        invoice_id TEXT NOT NULL,
        imported_at TEXT NOT NULL,
        invoice_hash_snapshot TEXT,
        FOREIGN KEY(sales_entry_id) REFERENCES sales_entries(id) ON DELETE CASCADE,
        FOREIGN KEY(invoice_id) REFERENCES invoices(id)
      )
    ''');
    await db.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_sales_entry_sources_unique ON sales_entry_sources(sales_entry_id, invoice_id)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS sales_receipts (
        id TEXT PRIMARY KEY,
        customer_id TEXT,
        payment_date TEXT NOT NULL,
        method TEXT,
        amount INTEGER NOT NULL,
        notes TEXT,
        created_at TEXT NOT NULL,
        updated_at TEXT NOT NULL,
        FOREIGN KEY(customer_id) REFERENCES customers(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_sales_receipts_date ON sales_receipts(payment_date)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS sales_receipt_links (
        receipt_id TEXT NOT NULL,
        sales_entry_id TEXT NOT NULL,
        allocated_amount INTEGER NOT NULL,
        PRIMARY KEY(receipt_id, sales_entry_id),
        FOREIGN KEY(receipt_id) REFERENCES sales_receipts(id) ON DELETE CASCADE,
        FOREIGN KEY(sales_entry_id) REFERENCES sales_entries(id) ON DELETE CASCADE
      )
    ''');
  }

  Future<void> _createPurchaseEntryTables(Database db) async {
    await db.execute('''
      CREATE TABLE IF NOT EXISTS purchase_entries (
        id TEXT PRIMARY KEY,
        supplier_id TEXT,
        supplier_name_snapshot TEXT,
        subject TEXT,
        issue_date TEXT NOT NULL,
        status TEXT NOT NULL,
        amount_tax_excl INTEGER DEFAULT 0,
        tax_amount INTEGER DEFAULT 0,
        amount_tax_incl INTEGER DEFAULT 0,
        notes TEXT,
        created_at TEXT NOT NULL,
        updated_at TEXT NOT NULL,
        FOREIGN KEY(supplier_id) REFERENCES suppliers(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_purchase_entries_supplier ON purchase_entries(supplier_id)');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_purchase_entries_issue_date ON purchase_entries(issue_date)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS purchase_line_items (
        id TEXT PRIMARY KEY,
        purchase_entry_id TEXT NOT NULL,
        product_id TEXT,
        description TEXT NOT NULL,
        quantity INTEGER NOT NULL,
        unit_price INTEGER NOT NULL,
        tax_rate REAL DEFAULT 0,
        line_total INTEGER DEFAULT 0,
        FOREIGN KEY(purchase_entry_id) REFERENCES purchase_entries(id) ON DELETE CASCADE,
        FOREIGN KEY(product_id) REFERENCES products(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_purchase_line_items_entry ON purchase_line_items(purchase_entry_id)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS purchase_receipts (
        id TEXT PRIMARY KEY,
        supplier_id TEXT,
        payment_date TEXT NOT NULL,
        method TEXT,
        amount INTEGER NOT NULL,
        notes TEXT,
        created_at TEXT NOT NULL,
        updated_at TEXT NOT NULL,
        FOREIGN KEY(supplier_id) REFERENCES suppliers(id)
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_purchase_receipts_supplier ON purchase_receipts(supplier_id)');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_purchase_receipts_payment_date ON purchase_receipts(payment_date)');

    await db.execute('''
      CREATE TABLE IF NOT EXISTS purchase_receipt_links (
        receipt_id TEXT NOT NULL,
        purchase_entry_id TEXT NOT NULL,
        allocated_amount INTEGER NOT NULL,
        PRIMARY KEY(receipt_id, purchase_entry_id),
        FOREIGN KEY(receipt_id) REFERENCES purchase_receipts(id) ON DELETE CASCADE,
        FOREIGN KEY(purchase_entry_id) REFERENCES purchase_entries(id) ON DELETE CASCADE
      )
    ''');
    await db.execute('CREATE INDEX IF NOT EXISTS idx_purchase_receipt_links_entry ON purchase_receipt_links(purchase_entry_id)');
  }
}
