using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading.Tasks;

namespace Beam.Api;
    public class ApiCallBuilder(HttpClient client) {
        HttpClient Client = client;
        string Uri;
        object? Data;
        object? Body;
        HttpMethod Method = HttpMethod.Get;
        List<KeyValuePair<string, List<string>>> Headers = [];
        HashSet<HttpStatusCode> SuccessCodes = [HttpStatusCode.OK];

        public ApiCallBuilder WithUri(string uri) {
            Uri = uri;
            return this;
        }

        public ApiCallBuilder WithUri(Uri uri) {
            return WithUri(uri.AbsoluteUri);
        }

        public ApiCallBuilder WithRequestData(object? data) {
            Data = data;
            return this;
        }

        public ApiCallBuilder WithBody(object? data) {
            Body = data;
            return this;
        }

        public ApiCallBuilder WithMethod(HttpMethod method) {
            Method = method;
            return this;
        }

        public ApiCallBuilder WithHeaders(IEnumerable<(string Key, IEnumerable<string> Value)> headers) {
            Headers = headers.Select((x) => new KeyValuePair<string, List<string>>(x.Key, x.Value.ToList())).ToList();
            return this;
        }

        public ApiCallBuilder WithSuccessCodes(params HashSet<HttpStatusCode> codes) {
            SuccessCodes = codes;
            return this;
        }

        public ApiCallBuilder WithSuccessCodes(params IEnumerable<int> codes) {
            SuccessCodes = codes.Cast<HttpStatusCode>().ToHashSet();
            return this;
        }

        public ApiCallBuilder AddHeader(string key, string value) {
            if (Headers.Any((x) => x.Key == key))
                Headers.FirstOrDefault((x) => x.Key == key).Value.Add(value);
            else
                Headers.Add(new KeyValuePair<string, List<string>>(key, [value]));
            return this;
        }

        public ApiCallBuilder AddBearer(string value)
            => AddHeader("Authorization", "Bearer " + value);

        public ApiCall Build() {
            if (Uri is null)
                throw new InvalidOperationException();
            if (Method is null)
                throw new InvalidOperationException();
            if (Headers is null)
                Headers = [];

            return new ApiCall(Client, Uri, Method, Headers.Select((x) => new KeyValuePair<string, string[]>(x.Key, x.Value.ToArray())).ToArray(), Data, Body, SuccessCodes);
        }
    }

