require "csv"

class Assistant::Function::ImportBankStatement < Assistant::Function
  class << self
    def name
      "import_bank_statement"
    end

    def description
      <<~INSTRUCTIONS
        Use this to import transactions from a bank statement PDF that has already been uploaded.

        This function will:
        1. Extract transaction data from the PDF using AI
        2. Create a transaction import with the extracted data
        3. Return the import ID and extracted transactions for review

        The PDF must have already been uploaded via the PDF import feature.
        Only use this for PDFs that are identified as bank statements.

        Example:

        ```
        import_bank_statement({
          pdf_import_id: "abc123-def456",
          account_id: "xyz789"
        })
        ```

        If account_id is not provided, you should ask the user which account to import to.
      INSTRUCTIONS
    end
  end

  def strict_mode?
    false
  end

  def params_schema
    build_schema(
      required: [ "pdf_import_id" ],
      properties: {
        pdf_import_id: {
          type: "string",
          description: "The ID of the PDF import to extract transactions from"
        },
        account_id: {
          type: "string",
          description: "The ID of the account to import transactions into. If not provided, will return available accounts."
        }
      }
    )
  end

  def call(params = {})
    pdf_import = family.imports.find_by(id: params["pdf_import_id"], type: "PdfImport")

    unless pdf_import
      return {
        success: false,
        error: "PDF import not found",
        message: "Could not find a PDF import with ID: #{params["pdf_import_id"]}"
      }
    end

    unless pdf_import.document_type == "bank_statement"
      return {
        success: false,
        error: "not_bank_statement",
        message: "This PDF is not a bank statement. Document type: #{pdf_import.document_type}",
        available_actions: [ "Use a different PDF that is a bank statement" ]
      }
    end

    # If no account specified, return available accounts
    if params["account_id"].blank?
      return {
        success: false,
        error: "account_required",
        message: "Please specify which account to import transactions into",
        available_accounts: family.accounts.visible.depository.map { |a| { id: a.id, name: a.name } }
      }
    end

    account = family.accounts.find_by(id: params["account_id"])
    unless account
      return {
        success: false,
        error: "account_not_found",
        message: "Account not found",
        available_accounts: family.accounts.visible.depository.map { |a| { id: a.id, name: a.name } }
      }
    end

    # Extract transactions from the PDF using provider
    provider = Provider::Registry.get_provider(:openai)
    unless provider
      return {
        success: false,
        error: "provider_not_configured",
        message: "OpenAI provider is not configured"
      }
    end

    response = provider.extract_bank_statement(
      pdf_content: pdf_import.pdf_file_content,
      model: openai_model,
      family: family
    )

    unless response.success?
      error_message = response.error&.message || "Unknown extraction error"
      return {
        success: false,
        error: "extraction_failed",
        message: "Failed to extract transactions: #{error_message}"
      }
    end

    result = response.data

    if result[:transactions].blank?
      return {
        success: false,
        error: "no_transactions_found",
        message: "Could not extract any transactions from the bank statement"
      }
    end

    # Create a CSV from extracted transactions
    csv_content = generate_csv(result[:transactions])

    # Create a TransactionImport
    import = family.imports.create!(
      type: "TransactionImport",
      account: account,
      raw_file_str: csv_content,
      date_col_label: "date",
      amount_col_label: "amount",
      name_col_label: "name",
      category_col_label: "category",
      notes_col_label: "notes",
      date_format: "%Y-%m-%d",
      signage_convention: "inflows_positive"
    )

    import.generate_rows_from_csv

    {
      success: true,
      import_id: import.id,
      transaction_count: result[:transactions].size,
      transactions_preview: result[:transactions].first(5),
      statement_period: result[:period],
      account_holder: result[:account_holder],
      message: "Successfully extracted #{result[:transactions].size} transactions. Import created with ID: #{import.id}. Review and publish when ready."
    }
  rescue Provider::Error, Faraday::Error, Timeout::Error, RuntimeError => e
    Rails.logger.error("ImportBankStatement error: #{e.class.name} - #{e.message}")
    Rails.logger.error(e.backtrace.first(10).join("\n"))
    {
      success: false,
      error: "extraction_failed",
      message: "Failed to extract transactions: #{e.message.truncate(200)}"
    }
  end

  private

    def generate_csv(transactions)
      CSV.generate do |csv|
        csv << %w[date amount name category notes]
        transactions.each do |txn|
          csv << [
            txn[:date],
            txn[:amount],
            txn[:name] || txn[:description],
            txn[:category],
            txn[:notes]
          ]
        end
      end
    end

    def openai_model
      ENV["OPENAI_MODEL"].presence || Provider::Openai::DEFAULT_MODEL
    end
end
