// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Apache.Arrow.Flight.Server;
using Apache.Arrow.Types;
using Arrow.Flight.Protocol.Sql;
using Google.Protobuf;
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using Microsoft.Extensions.Logging;

namespace Apache.Arrow.Flight.Sql;

public abstract class FlightSqlServer : FlightServer
{
    private ILogger? Logger { get; }
    public static readonly Schema CatalogSchema = new(new List<Field> { new("catalog_name", StringType.Default, false) }, null);
    public static readonly Schema TableTypesSchema = new(new List<Field> { new("table_type", StringType.Default, false) }, null);
    public static readonly Schema DbSchemaFlightSchema = new(new List<Field> { new("catalog_name", StringType.Default, true), new("db_schema_name", StringType.Default, false) }, null);

    public static readonly Schema PrimaryKeysSchema = new(new List<Field>
    {
        new("catalog_name", StringType.Default, true),
        new("db_schema_name", StringType.Default, true),
        new("table_name", StringType.Default, false),
        new("column_name", StringType.Default, false),
        new("key_sequence", Int32Type.Default, false),
        new("key_name", StringType.Default, true)
    }, null);

    public static readonly Schema KeyImportExportSchema = new(new List<Field>
    {
        new("pk_catalog_name", StringType.Default, true),
        new("pk_db_schema_name", StringType.Default, true),
        new("pk_table_name", StringType.Default, false),
        new("pk_column_name", StringType.Default, false),
        new("fk_catalog_name", StringType.Default, true),
        new("fk_db_schema_name", StringType.Default, true),
        new("fk_table_name", StringType.Default, false),
        new("fk_column_name", StringType.Default, false),
        new("key_sequence", Int32Type.Default, false),
        new("fk_key_name", StringType.Default, true),
        new("pk_key_name", StringType.Default, true),
        new("update_rule", UInt8Type.Default, false),
        new("delete_rule", UInt8Type.Default, false)
    }, null);

    public static readonly Schema TypeInfoSchema = new(new List<Field>
    {
        new("type_name", StringType.Default, false),
        new("data_type", Int32Type.Default, false),
        new("column_size", Int32Type.Default, true),
        new("literal_prefix", StringType.Default, true),
        new("literal_suffix", StringType.Default, true),
        new("create_params", new ListType(new Field("item", StringType.Default, false)), true),
        new("nullable", Int32Type.Default, false),
        new("case_sensitive", BooleanType.Default, false),
        new("searchable", Int32Type.Default, false),
        new("unsigned_attribute", BooleanType.Default, true),
        new("fixed_prec_scale", BooleanType.Default, false),
        new("auto_increment", BooleanType.Default, true),
        new("local_type_name", StringType.Default, true),
        new("minimum_scale", Int32Type.Default, true),
        new("maximum_scale", Int32Type.Default, true),
        new("sql_data_type", Int32Type.Default, false),
        new("datetime_subcode", Int32Type.Default, true),
        new("num_prec_radix", Int32Type.Default, true),
        new("interval_precision", Int32Type.Default, true)
    }, null);

    public static readonly Schema SqlInfoSchema = new(new List<Field>
    {
        new("info_name", UInt32Type.Default, false)
        //TODO: once we have union serialization in Arrow Flight for .Net we should to add these fields
        // fieldList.Add(new Field("value", new UnionType(new List<Field>(), new List<byte>()), false));
        // fieldList.Add(new Field("value", new UnionType(new []
        // {
        //     new Field("string_value", StringType.Default, false),
        //     new Field("bool_value", BooleanType.Default, false),
        //     new Field("bigint_value", Int64Type.Default, false),
        //     new Field("bool_value", BooleanType.Default, false),
        //     new Field("bigint_value", Int64Type.Default, false),
        //     new Field("int32_bitmask", Int32Type.Default, false),
        //     new Field("string_list", new ListType(new Field("item", StringType.Default, false)), false),
        //     new Field("int32_to_int32_list_map", new DictionaryType(Int32Type.Default, new ListType(Int32Type.Default), false), false),
        // }, new []{(byte)ArrowTypeId.String, (byte)ArrowTypeId.Boolean, (byte)ArrowTypeId.Int64,/* (byte)3, (byte)4, (byte)5*/}, UnionMode.Dense), false));
    }, null);

    private static readonly Schema s_tableSchema = new(new List<Field>
    {
        new("catalog_name", StringType.Default, true),
        new("db_schema_name", StringType.Default, true),
        new("table_name", StringType.Default, false),
        new("table_type", StringType.Default, false)
    }, null);

    public static Schema GetTableSchema(bool includeTableSchemaField)
    {
        if (!includeTableSchemaField)
        {
            return s_tableSchema;
        }

        var fields = s_tableSchema.FieldsList.ToList();
        fields.Add(new Field("table_schema", BinaryType.Default, false));

        return new Schema(fields, s_tableSchema.Metadata);
    }

    public static IMessage? GetCommand(FlightTicket ticket)
    {
        try
        {
            return GetCommand(Any.Parser.ParseFrom(ticket.Ticket));
        }
        catch (InvalidProtocolBufferException) { } //The ticket is not a flight sql command

        return null;
    }

    public static async Task<IMessage?> GetCommand(FlightServerRecordBatchStreamReader requestStream)
    {
        return GetCommand(await requestStream.FlightDescriptor.ConfigureAwait(false));
    }

    public static IMessage? GetCommand(FlightDescriptor? request)
    {
        if (request == null) return null;
        if (request.Type == FlightDescriptorType.Command && request.ParsedAndUnpackedMessage() is { } command)
        {
            return command;
        }

        return null;
    }

    private static IMessage? GetCommand(Any command)
    {
        if (command.Is(CommandPreparedStatementQuery.Descriptor))
        {
            return command.Unpack<CommandPreparedStatementQuery>();
        }

        if (command.Is(CommandGetSqlInfo.Descriptor))
        {
            return command.Unpack<CommandGetSqlInfo>();
        }

        if (command.Is(CommandGetCatalogs.Descriptor))
        {
            return command.Unpack<CommandGetCatalogs>();
        }

        if (command.Is(CommandGetTableTypes.Descriptor))
        {
            return command.Unpack<CommandGetTableTypes>();
        }

        if (command.Is(CommandGetTables.Descriptor))
        {
            return command.Unpack<CommandGetTables>();
        }

        if (command.Is(CommandGetDbSchemas.Descriptor))
        {
            return command.Unpack<CommandGetDbSchemas>();
        }

        if (command.Is(CommandGetPrimaryKeys.Descriptor))
        {
            return command.Unpack<CommandGetPrimaryKeys>();
        }

        if (command.Is(CommandGetExportedKeys.Descriptor))
        {
            return command.Unpack<CommandGetExportedKeys>();
        }

        if (command.Is(CommandGetImportedKeys.Descriptor))
        {
            return command.Unpack<CommandGetImportedKeys>();
        }

        if (command.Is(CommandGetCrossReference.Descriptor))
        {
            return command.Unpack<CommandGetCrossReference>();
        }

        if (command.Is(CommandGetXdbcTypeInfo.Descriptor))
        {
            return command.Unpack<CommandGetXdbcTypeInfo>();
        }

        return null;
    }

    protected FlightSqlServer(ILoggerFactory? factory = null)
    {
        Logger = factory?.CreateLogger(typeof(FlightSqlServer));
    }

    /// <summary>
    /// Lists actions supported by Flight SQL.  For Flight RPC actions support
    /// implementers should extend this method to return additional supported actions.
    /// </summary>
    public override async Task ListActions(IAsyncStreamWriter<FlightActionType> responseStream, ServerCallContext context)
    {
        foreach (var actionType in FlightSqlUtils.FlightSqlActions)
        {
            await responseStream.WriteAsync(actionType).ConfigureAwait(false);
        }
    }

    /// <summary>
    /// Attempts to execute a valid Flight SQL command.  For Flight RPC calls
    /// implementers should extend this method in order to handle RPC messages.
    /// </summary>
    public override Task<FlightInfo> GetFlightInfo(FlightDescriptor flightDescriptor, ServerCallContext context)
    {
        var sqlCommand = GetCommand(flightDescriptor);
        Logger?.LogTrace("Executing Flight SQL FlightInfo command: {DescriptorName}", sqlCommand?.Descriptor.Name);
        return sqlCommand switch
        {
            CommandStatementQuery command => GetStatementQueryFlightInfo(command, flightDescriptor, context),
            CommandPreparedStatementQuery command => GetPreparedStatementQueryFlightInfo(command, flightDescriptor, context),
            CommandGetCatalogs command => GetCatalogFlightInfo(command, flightDescriptor, context),
            CommandGetDbSchemas command => GetDbSchemaFlightInfo(command, flightDescriptor, context),
            CommandGetTables command => GetTablesFlightInfo(command, flightDescriptor, context),
            CommandGetTableTypes command => GetTableTypesFlightInfo(command, flightDescriptor, context),
            CommandGetSqlInfo command => GetSqlFlightInfo(command, flightDescriptor, context),
            CommandGetPrimaryKeys command => GetPrimaryKeysFlightInfo(command, flightDescriptor, context),
            CommandGetExportedKeys command => GetExportedKeysFlightInfo(command, flightDescriptor, context),
            CommandGetImportedKeys command => GetImportedKeysFlightInfo(command, flightDescriptor, context),
            CommandGetCrossReference command => GetCrossReferenceFlightInfo(command, flightDescriptor, context),
            CommandGetXdbcTypeInfo command => GetXdbcTypeFlightInfo(command, flightDescriptor, context),
            _ => throw new InvalidOperationException($"command type {sqlCommand?.Descriptor?.Name} not supported")
        };
    }

    /// <summary>
    /// Attempts to execute a valid Flight SQL command.  For Flight RPC calls
    /// implementers should extend this method in order to handle RPC messages.
    /// </summary>
    public override Task DoGet(FlightTicket ticket, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context)
    {
        var sqlCommand = GetCommand(ticket);
        Logger?.LogTrace("Executing Flight SQL DoGet command: {SqlCommandDescriptor}", sqlCommand?.Descriptor);
        return sqlCommand switch
        {
            CommandPreparedStatementQuery command => DoGetPreparedStatementQuery(command, responseStream, context),
            CommandGetSqlInfo command => DoGetSqlInfo(command, responseStream, context),
            CommandGetCatalogs command => DoGetCatalog(command, responseStream, context),
            CommandGetTableTypes command => DoGetTableType(command, responseStream, context),
            CommandGetTables command => DoGetTables(command, responseStream, context),
            CommandGetDbSchemas command => DoGetDbSchema(command, responseStream, context),
            CommandGetPrimaryKeys command => DoGetPrimaryKeys(command, responseStream, context),
            CommandGetExportedKeys command => DoGetExportedKeys(command, responseStream, context),
            CommandGetImportedKeys command => DoGetImportedKeys(command, responseStream, context),
            CommandGetCrossReference command => DoGetCrossReference(command, responseStream, context),
            CommandGetXdbcTypeInfo command => DoGetXbdcTypeInfo(command, responseStream, context),
            _ => throw new RpcException(new Status(StatusCode.InvalidArgument, $"DoGet command {sqlCommand?.Descriptor} is not supported."))
        };
    }

    /// <summary>
    /// Attempts to execute a valid Flight SQL command.  For Flight RPC calls
    /// implementers should extend this method in order to handle RPC messages.
    /// </summary>
    public override Task DoAction(FlightAction action, IAsyncStreamWriter<FlightResult> responseStream, ServerCallContext context)
    {
        Logger?.LogTrace("Executing Flight SQL DoAction: {ActionType}", action.Type);
        switch (action.Type)
        {
            case SqlAction.CreateRequest:
                var command = FlightSqlUtils.ParseAndUnpack<ActionCreatePreparedStatementRequest>(action.Body);
                return CreatePreparedStatement(command, action, responseStream, context);
            case SqlAction.CloseRequest:
                var closeCommand = FlightSqlUtils.ParseAndUnpack<ActionClosePreparedStatementRequest>(action.Body);
                return ClosePreparedStatement(closeCommand, action, responseStream, context);
            default:
                throw new NotImplementedException($"Action type {action.Type} not supported");
        }
    }

    /// <summary>
    /// Attempts to execute a valid Flight SQL command.  For Flight RPC calls
    /// implementers should extend this method in order to handle RPC messages.
    /// </summary>
    public override async Task DoPut(FlightServerRecordBatchStreamReader requestStream, IAsyncStreamWriter<FlightPutResult> responseStream, ServerCallContext context)
    {
        if (await GetCommand(requestStream).ConfigureAwait(false) is { } command)
        {
            await DoPutInternal(command, requestStream, responseStream, context).ConfigureAwait(false);
        }
        else
        {
            throw new NotImplementedException();
        }
    }

    private Task DoPutInternal(IMessage command, FlightServerRecordBatchStreamReader requestStream, IAsyncStreamWriter<FlightPutResult> responseStream, ServerCallContext context)
    {
        Logger?.LogTrace("Executing Flight SQL DoAction: {DescriptorName}", command.Descriptor.Name);
        return command switch
        {
            CommandStatementUpdate statementUpdate => PutStatementUpdate(statementUpdate, requestStream, responseStream, context),
            CommandPreparedStatementQuery preparedStatementQuery => PutPreparedStatementQuery(preparedStatementQuery, requestStream, responseStream, context),
            CommandPreparedStatementUpdate preparedStatementUpdate => PutPreparedStatementUpdate(preparedStatementUpdate, requestStream, responseStream, context),
            _ => throw new NotImplementedException($"Command {command.Descriptor.Name} not supported")
        };
    }

    public static bool SupportsAction(FlightAction action)
    {
        switch (action.Type)
        {
            case SqlAction.CreateRequest:
            case SqlAction.CloseRequest:
                return true;
            default:
                return false;
        }
    }


    #region FlightInfo

    protected abstract Task<FlightInfo> GetStatementQueryFlightInfo(CommandStatementQuery commandStatementQuery, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetPreparedStatementQueryFlightInfo(CommandPreparedStatementQuery preparedStatementQuery, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetCatalogFlightInfo(CommandGetCatalogs command, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetDbSchemaFlightInfo(CommandGetDbSchemas command, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetTablesFlightInfo(CommandGetTables command, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetTableTypesFlightInfo(CommandGetTableTypes command, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetSqlFlightInfo(CommandGetSqlInfo commandGetSqlInfo, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetPrimaryKeysFlightInfo(CommandGetPrimaryKeys command, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetExportedKeysFlightInfo(CommandGetExportedKeys command, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetImportedKeysFlightInfo(CommandGetImportedKeys command, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetCrossReferenceFlightInfo(CommandGetCrossReference command, FlightDescriptor flightDescriptor, ServerCallContext context);
    protected abstract Task<FlightInfo> GetXdbcTypeFlightInfo(CommandGetXdbcTypeInfo command, FlightDescriptor flightDescriptor, ServerCallContext context);

    #endregion

    #region DoGet

    protected abstract Task DoGetPreparedStatementQuery(CommandPreparedStatementQuery preparedStatementQuery, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetSqlInfo(CommandGetSqlInfo getSqlInfo, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetCatalog(CommandGetCatalogs command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetTableType(CommandGetTableTypes command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetTables(CommandGetTables command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetPrimaryKeys(CommandGetPrimaryKeys command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetDbSchema(CommandGetDbSchemas command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetExportedKeys(CommandGetExportedKeys command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetImportedKeys(CommandGetImportedKeys command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetCrossReference(CommandGetCrossReference command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);
    protected abstract Task DoGetXbdcTypeInfo(CommandGetXdbcTypeInfo command, FlightServerRecordBatchStreamWriter responseStream, ServerCallContext context);

    #endregion

    #region DoAction

    protected abstract Task CreatePreparedStatement(ActionCreatePreparedStatementRequest request, FlightAction action, IAsyncStreamWriter<FlightResult> streamWriter, ServerCallContext context);
    protected abstract Task ClosePreparedStatement(ActionClosePreparedStatementRequest request, FlightAction action, IAsyncStreamWriter<FlightResult> streamWriter, ServerCallContext context);

    #endregion

    #region DoPut

    protected abstract Task PutPreparedStatementUpdate(CommandPreparedStatementUpdate command, FlightServerRecordBatchStreamReader requestStream, IAsyncStreamWriter<FlightPutResult> responseStream, ServerCallContext context);
    protected abstract Task PutStatementUpdate(CommandStatementUpdate command, FlightServerRecordBatchStreamReader requestStream, IAsyncStreamWriter<FlightPutResult> responseStream, ServerCallContext context);
    protected abstract Task PutPreparedStatementQuery(CommandPreparedStatementQuery command, FlightServerRecordBatchStreamReader requestStream, IAsyncStreamWriter<FlightPutResult> responseStream, ServerCallContext context);

    #endregion
}
