using Amazon.S3.Model;
using Microsoft.AspNetCore.Http;
using OnlineAssessment.Helpers;
using OnlineAssessment.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace OnlineAssessment.Services
{
    public interface IAWSS3FileService
    {
        Task<string> UploadFile(string uploadFileName);
        //Task<bool> UploadProfileImage(int institute_id, int user_id, string uploadFileName);
        Task<Object> UploadProfileImage(int institute_id, int user_id, IFormFile file);
        Task<Object> UploadExamImage(int institute_id, int user_id, int exam_id, IFormFile file);
        Task<Object> UploadPracticeImage(int institute_id, int user_id, int practice_id, IFormFile file);
        Task<Object> UploadQuestionImage(int institute_id, IFormFile file);

        Task<List<FilePathWithMeta>> FilesList();
        Task<Stream> GetFile(int institute_id, int user_id, string folder, string key);
        Task<string> UpdateFile(UploadFileName uploadFileName, string key);
        Task<bool> DeleteFile(string key);
        Task<bool> DeleteProfileImage(int institute_id, int user_id);
    }
    public class AWSS3FileService : IAWSS3FileService
    {
        private readonly IAWSS3BucketHelper _AWSS3BucketHelper;

        public AWSS3FileService(IAWSS3BucketHelper AWSS3BucketHelper)
        {
            this._AWSS3BucketHelper = AWSS3BucketHelper;
        }
        public async Task<string> UploadFile(string uploadFileName)
        {
            try
            {
                var path = Path.Combine(uploadFileName.ToString());
                using (FileStream fsSource = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    string fileExtension = Path.GetExtension(path);
                    string fileName = string.Empty;
                    fileName = $"{DateTime.Now.Ticks}{fileExtension}";
                    return await _AWSS3BucketHelper.UploadFile(fsSource, path);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /*
        public async Task<bool> UploadProfileImage(int institute_id, int user_id, string uploadFileName)
        {
            try
            {
                var path = Path.Combine(uploadFileName.ToString());
                using (FileStream fsSource = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    string fileExtension = Path.GetExtension(path);
                    string fileName = string.Empty;
                    string folder = "/user-photo/";
                    fileName = $"{institute_id.ToString()}{folder}{user_id.ToString()}{fileExtension}";
                    return await _AWSS3BucketHelper.UploadFile(fsSource, fileName);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        } 
        */

        public async Task<Object> UploadProfileImage(int institute_id, int user_id, IFormFile file)
        {
            try
            {
                IList<string> AllowedFileExtensions = new List<string> { ".png", ".jpg", ".jpeg" };
                string fileExtension = Path.GetExtension(file.FileName.ToString()).ToLower();
                if (!AllowedFileExtensions.Contains(fileExtension))
                {
                    var message = string.Format("Please Upload image of type .png or .jpg");
                    return message;
                }
                fileExtension = ".png";
                string fileName = string.Empty;
                string folder = "/user-photo/";
                fileName = $"{institute_id.ToString()}{folder}{user_id.ToString()}{fileExtension}";
                return await _AWSS3BucketHelper.UploadFile(file.OpenReadStream(), fileName);
                
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public async Task<Object> UploadExamImage(int institute_id, int user_id, int exam_id, IFormFile file)
        {
            try
            {
                IList<string> AllowedFileExtensions = new List<string> { ".png", ".jpg", ".jpeg" };
                string fileExtension = Path.GetExtension(file.FileName.ToString()).ToLower();
                if (!AllowedFileExtensions.Contains(fileExtension))
                {
                    var message = string.Format("Please Upload image of type .png., jpg, jpeg");
                    return message;
                }
                string fileName = string.Empty;
                string folder = "/exams/";
                fileExtension = ".png";
                fileName = $"{institute_id.ToString()}{folder}{exam_id.ToString()}{fileExtension}";
                return await _AWSS3BucketHelper.UploadFile(file.OpenReadStream(), fileName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public async Task<Object> UploadPracticeImage(int institute_id, int user_id, int practice_id, IFormFile file)
        {
            try
            {
                IList<string> AllowedFileExtensions = new List<string> { ".png", ".jpg", ".jpeg" };
                string fileExtension = Path.GetExtension(file.FileName.ToString()).ToLower();
                if (!AllowedFileExtensions.Contains(fileExtension))
                {
                    var message = string.Format("Please Upload image of type .png.");
                    return message;
                }
                string fileName = string.Empty;
                string folder = "/practices/";
                fileExtension = ".png";
                fileName = $"{institute_id.ToString()}{folder}{practice_id.ToString()}{fileExtension}";
                return await _AWSS3BucketHelper.UploadFile(file.OpenReadStream(), fileName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        public async Task<Object> UploadQuestionImage(int institute_id, IFormFile file)
        {
            try
            {
                // Allowed file types
                IList<string> AllowedFileExtensions = new List<string> { ".png", ".jpg", ".jpeg" };
                string fileExtension = Path.GetExtension(file.FileName).ToLower();

                if (!AllowedFileExtensions.Contains(fileExtension))
                {
                    throw new Exception("Please upload an image of type .png, .jpg, or .jpeg");
                }

                string folder = "/questions/";
                fileExtension = ".png";

                // Create a unique file name (so older uploads don't get overwritten)
                string uniqueFileName = $"{institute_id}/{folder}/{Guid.NewGuid()}{fileExtension}";

                // Upload file to S3
                return await _AWSS3BucketHelper.UploadFile(file.OpenReadStream(), uniqueFileName);
            }
            catch (Exception ex)
            {
                throw new Exception($"Image upload failed: {ex.Message}");
            }
        }


        public async Task<List<FilePathWithMeta>> FilesList()
        {
            try
            {
                GetObjectMetadataResponse meta = new GetObjectMetadataResponse();
                KeyValue kv = new KeyValue();
                List<KeyValue> lkv = new List<KeyValue>();
                FilePathWithMeta metaFile = new FilePathWithMeta();
                List<FilePathWithMeta> listMetaFile = new List<FilePathWithMeta>();

                ListVersionsResponse listVersions = await _AWSS3BucketHelper.FilesList();
                List<string> filenamelist = listVersions.Versions.Select(c => c.Key).ToList();
                filenamelist = filenamelist.Where(r => r.EndsWith("png")).ToList();

                foreach(string name in filenamelist)
                {
                    meta = await _AWSS3BucketHelper.MetaDetail(name);
                    foreach (string key in meta.Metadata.Keys)
                    {
                        kv.key = key;
                        kv.value = meta.Metadata[key];
                        lkv.Add(kv);
                    }
                     
                    metaFile.file_path = name;
                    metaFile.listmetadata = lkv;
                    listMetaFile.Add(metaFile);
                }

                return listMetaFile;
                  
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
        public async Task<Stream> GetFile(int institute_id, int user_id, string folder, string key)
        {
            //string fileExtension = ".png";
            string fileName = string.Empty;
            fileName = $"{institute_id.ToString()}{folder}{key.ToString()}";

            try
            {
                Stream fileStream = await _AWSS3BucketHelper.GetFile(fileName);
                if (fileStream == null)
                {
                    Exception ex = new Exception("File Not Found");
                    throw ex;
                }
                else
                {
                    return fileStream;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public async Task<string> UpdateFile(UploadFileName uploadFileName, string key)
        {
            try
            {
                var path = Path.Combine("Files", uploadFileName.ToString() + ".png");
                using (FileStream fsSource = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    return await _AWSS3BucketHelper.UploadFile(fsSource, key);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public async Task<bool> DeleteProfileImage(int institute_id, int user_id)
        {
            try
            {
                string fileExtension = ".png";
                string fileName = string.Empty;
                string folder = "/user-photo/";
                fileName = $"{institute_id.ToString()}{folder}{user_id.ToString()}{fileExtension}";

                return await _AWSS3BucketHelper.DeleteFile(fileName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public async Task<bool> DeleteFile(string key)
        {
            try
            {
                return await _AWSS3BucketHelper.DeleteFile(key);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}