using Books.Api.EventFlow.ReadModels;
using Books.Api.EventFlow.Repositories;
using GraphQL.Types;

namespace Books.Api.GraphQL.Types;

public class BankConnectionType : ObjectGraphType<BankConnectionReadModelDto>
{
    public BankConnectionType()
    {
        Name = "BankConnection";
        Description = "A bank connection for open banking access";

        Field(x => x.Id).Description("The bank connection ID");
        Field(x => x.CompanyId).Description("The company ID");
        Field(x => x.AspspName).Description("The bank name (ASPSP)");
        Field(x => x.Status).Description("Connection status: initiated, established, failed, disconnected");
        Field(x => x.ValidUntil, nullable: true).Description("When the connection expires");
        Field(x => x.FailureReason, nullable: true).Description("Failure reason if status is failed");
        Field(x => x.CreatedAt).Description("When the connection was initiated");
        Field(x => x.UpdatedAt).Description("When the connection was last updated");
        Field(x => x.IsActive).Description("Whether the connection is currently active");
        Field(x => x.IsArchived).Description("Whether this connection is archived");

        Field<ListGraphType<BankAccountInfoType>>("accounts")
            .Description("Available bank accounts from this connection")
            .Resolve(ctx => ctx.Source.Accounts);
    }
}

public class BankAccountInfoType : ObjectGraphType<Domain.BankConnections.BankAccountInfo>
{
    public BankAccountInfoType()
    {
        Name = "BankAccountInfo";
        Description = "Information about a bank account from Open Banking";

        Field(x => x.AccountId).Description("The bank's account identifier");
        Field(x => x.Iban).Description("The IBAN number");
        Field(x => x.Currency).Description("The account currency");
        Field(x => x.Name, nullable: true).Description("The account name");
        Field(x => x.LinkedAccountId, nullable: true).Description("The linked chart of accounts account ID");
        Field(x => x.ImportFromDate, nullable: true).Description("Date to start importing transactions from");

        Field<AccountGraphType>("linkedAccount")
            .Description("The linked chart of accounts account")
            .ResolveAsync(async ctx =>
            {
                if (string.IsNullOrEmpty(ctx.Source.LinkedAccountId))
                    return null;

                var accountRepo = ctx.RequestServices!.GetRequiredService<IAccountRepository>();
                return await accountRepo.GetByIdAsync(ctx.Source.LinkedAccountId, ctx.CancellationToken);
            });
    }
}

public class AspspType : ObjectGraphType<Banking.Aspsp>
{
    public AspspType()
    {
        Name = "Aspsp";
        Description = "A bank (ASPSP) available for connection via Open Banking";

        Field(x => x.Name).Description("The bank name");
        Field(x => x.Country).Description("The country code");
        Field(x => x.Logo).Description("URL to the bank logo");
        Field<ListGraphType<StringGraphType>>("psuTypes")
            .Description("Supported PSU types (personal, business)")
            .Resolve(ctx => ctx.Source.PsuTypes);
        Field(x => x.PersonalAccounts).Description("Whether personal accounts are supported");
        Field(x => x.BusinessAccounts).Description("Whether business accounts are supported");
    }
}

public class StartBankConnectionResultType : ObjectGraphType<StartBankConnectionResult>
{
    public StartBankConnectionResultType()
    {
        Name = "StartBankConnectionResult";
        Description = "Result from starting a bank connection";

        Field(x => x.ConnectionId).Description("The bank connection ID");
        Field(x => x.AuthorizationUrl).Description("URL to redirect the user for bank authorization");
    }
}

public class StartBankConnectionResult
{
    public string ConnectionId { get; set; } = string.Empty;
    public string AuthorizationUrl { get; set; } = string.Empty;
}
