import os
from dataclasses import dataclass
from datetime import date

from temporalio import common
from temporalio.client import WithStartWorkflowOperation, WorkflowUpdateFailedError

from shared.config import get_temporal_client


# Define data structures to match the Java workflow's expected input/output
# see https://github.com/temporal-sa/temporal-latency-optimization-scenarios for more details
@dataclass
class TransactionRequest:
    amount: float
    sourceAccount: str
    targetAccount: str


@dataclass
class TxResult:
    transactionId: str
    status: str


# demonstrate starting a workflow and early return pattern while the workflow continues
async def submit_loan_application(args: dict) -> dict:
    account_key = args.get("email_address_or_account_ID")
    amount = args.get("amount")

    loan_status: dict = await start_workflow(amount=amount, account_name=account_key)

    if loan_status.get("error") is None:
        return {
            "status": loan_status.get("loan_application_status"),
            "detailed_status": loan_status.get("application_details"),
            "next_step": loan_status.get("advisement"),
            "confirmation_id": loan_status.get("transaction_id"),
        }
    else:
        print(loan_status)
        return loan_status


# Async function to start workflow
async def start_workflow(
    amount: str,
    account_name: str,
) -> dict:
    start_real_workflow = os.getenv("FIN_START_REAL_WORKFLOW")
    if start_real_workflow is not None and start_real_workflow.lower() == "false":
        # START_REAL_WORKFLOW = False
        return {
            "loan_application_status": "applied",
            "application_details": "loan application is submitted and initial validation is complete",
            "transaction_id": "APPLICATION" + account_name,
            "advisement": "You'll receive a confirmation for final approval in three business days",
        }
    else:
        # START_REAL_WORKFLOW = True
        # Connect to Temporal
        client = await get_temporal_client()

        # Define the workflow ID and task queue
        workflow_id = (
            "LOAN_APPLICATION-" + account_name + "-" + date.today().strftime("%Y-%m-%d")
        )
        task_queue = "LatencyOptimizationTEST"

        # Create a TransactionRequest (matching the Java workflow's expected input)
        tx_request = TransactionRequest(
            amount=float(amount),
            targetAccount=account_name,
            sourceAccount=account_name,
        )

        start_op = WithStartWorkflowOperation(
            "TransactionWorkflowLocalBeforeUpdate",
            tx_request,
            id=workflow_id,
            id_conflict_policy=common.WorkflowIDConflictPolicy.USE_EXISTING,
            task_queue=task_queue,
        )

        try:
            print("trying update-with-start")
            tx_result = TxResult(
                await client.execute_update_with_start_workflow(
                    "returnInitResult",
                    start_workflow_operation=start_op,
                )
            )
        except WorkflowUpdateFailedError:
            print("aww man got exception WorkflowUpdateFailedError")
            tx_result = None
            return_msg = "Loan could not be processed for " + account_name
            return {"error": return_msg}

        workflow_handle = await start_op.workflow_handle()
        print(f"Workflow started with ID: {workflow_handle.id}")
        print(tx_result)

        print(
            f"Update result: Transaction ID = {tx_result.transactionId}, Message = {tx_result.status}"
        )

        # Optionally, wait for the workflow to complete and get the final result
        # final_result = await handle.result()
        # print(f"Workflow completed with result: {final_result}")

        # return {'status': loan_status.get("loan_status"), 'detailed_status': loan_status.get("results"), 'next_step': loan_status.get("advisement"), 'confirmation_id': loan_status.get("workflowID")}
        return {
            "loan_application_status": "applied",
            "application_details": "loan application is submitted and initial validation is complete",
            "transaction_id": tx_result.transactionId,
            "advisement": "You'll receive a confirmation for final approval in three business days",
        }
