package main

// @title Tender Management API
// @version 2.0.0
// @description This is a comprehensive API for the Tender Management System built with Clean Architecture principles and Domain-Driven Design (DDD) patterns. The API provides endpoints for user management, customer management, company management, and authentication for both web panel administration and mobile application access.
// @termsOfService https://tender-management.com/terms

// @contact.name Tender Management API Support
// @contact.url https://tender-management.com/support
// @contact.email api-support@tender-management.com

// @license.name MIT
// @license.url https://opensource.org/licenses/MIT

// @host localhost:8082
// @BasePath /

// @securityDefinitions.apikey BearerAuth
// @in header
// @name Authorization
// @description Type "Bearer" followed by a space and JWT token. Example: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

// @tag.name Admin-Health
// @tag.description System health check operations for monitoring application status and dependencies

// @tag.name Admin-Authorization
// @tag.description User authentication and authorization operations including login, logout, token refresh, and password management for web panel administration

// @tag.name Admin-Users
// @tag.description Administrative user management operations including CRUD operations, role management, status updates, and profile management for web panel administrators

// @tag.name Admin-Customers
// @tag.description Administrative customer management operations for web panel including CRUD operations, company assignment, verification, status management, and comprehensive filtering with pagination

// @tag.name Admin-Companies
// @tag.description Administrative company management operations for web panel including CRUD operations, tag management, verification, status updates, comprehensive search and filtering, and statistical reporting

// @tag.name Admin-Tenders
// @tag.description Administrative tender management operations for web panel including CRUD operations, search, statistics, and comprehensive filtering with pagination

// @tag.name Admin-Feedback
// @tag.description Administrative feedback management operations for web panel including CRUD operations, search, statistics, and comprehensive filtering with pagination

// @tag.name Admin-TenderApprovals
// @tag.description Administrative tender approval management operations for web panel including CRUD operations, search, statistics, and comprehensive filtering with pagination

// @tag.name Authorization
// @tag.description Customer authentication and authorization operations for mobile application including login, logout, token refresh, and profile access

// @tag.name Company
// @tag.description Company information access for mobile application including company profile and company tenders

// @tag.name Tenders
// @tag.description Public tender information access for mobile application including active tender listings and detailed tender information

// @tag.name Feedback
// @tag.description Public feedback management operations for mobile application including like, dislike, and comment on tenders

// @tag.name TenderApprovals
// @tag.description Public tender approval management operations for mobile application including tender approval listing and detailed tender approval information

import (
	"context"
	"fmt"
	"net/http"
	"time"
	"tm/internal/company"
	"tm/internal/customer"
	"tm/internal/feedback"
	"tm/internal/tender"
	"tm/internal/tender_approval"
	"tm/internal/user"

	"tm/cmd/web/bootstrap"
	_ "tm/cmd/web/docs" // This is generated by swag
	"tm/cmd/web/router"
)

func main() {
	conf := bootstrap.InitConfig()

	logger := bootstrap.InitLogger(conf.Logging)
	defer logger.Sync()

	// Initialize MongoDB connection manager
	mongoManager := bootstrap.InitMongoDB(conf.Database.MongoDB, logger)
	defer func() {
		ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
		defer cancel()
		if err := mongoManager.Close(ctx); err != nil {
			logger.Error("Failed to close MongoDB connection", map[string]interface{}{
				"error": err.Error(),
			})
		}
	}()

	// Initialize Redis connection manager
	redisClient := bootstrap.InitRedis(conf.Cache.Redis, logger)
	defer func() {
		if err := redisClient.Close(); err != nil {
			logger.Error("Failed to close Redis connection", map[string]interface{}{
				"error": err.Error(),
			})
		}
	}()

	// Initialize authorization service
	userAuthService := bootstrap.InitAuthorizationService(conf.UserAuth.JWT, redisClient, logger)
	customerAuthService := bootstrap.InitAuthorizationService(conf.CustomerAuth.JWT, redisClient, logger)

	// Initialize repositories with MongoDB connection manager
	userRepository := user.NewUserRepository(mongoManager, logger)
	customerRepository := customer.NewCustomerRepository(mongoManager, logger)
	companyRepository := company.NewCompanyRepository(mongoManager, logger)
	tenderRepository := tender.NewTenderRepository(mongoManager, logger)
	feedbackRepo := feedback.NewFeedbackRepository(mongoManager, logger)
	tenderApprovalRepository := tender_approval.NewTenderApprovalRepository(mongoManager, logger)
	logger.Info("Repositories initialized successfully", map[string]interface{}{
		"repositories": []string{"customer", "user", "company", "tender", "feedback", "tender_approval"},
	})

	// Initialize validation service
	userValidator := user.NewValidationService()

	// Initialize services with repositories
	userService := user.NewUserService(userRepository, logger, userAuthService, userValidator)
	companyService := company.NewCompanyService(companyRepository, logger)
	customerService := customer.NewCustomerService(customerRepository, logger, customerAuthService, companyService)
	tenderService := tender.NewTenderService(tenderRepository, companyService, logger)
	feedbackService := feedback.NewFeedbackService(feedbackRepo, tenderService, logger)
	tenderApprovalService := tender_approval.NewTenderApprovalService(tenderApprovalRepository, tenderService, logger)
	logger.Info("Services initialized successfully", map[string]interface{}{
		"services": []string{"customer", "user", "company", "tender", "feedback", "tender_approval"},
	})

	// Initialize handlers with services
	userHandler := user.NewUserHandler(userService, logger, userValidator, userAuthService)
	customerHandler := customer.NewHandler(customerService, userHandler, customerAuthService, logger)
	companyHandler := company.NewHandler(companyService, userHandler, logger)
	tenderHandler := tender.NewTenderHandler(tenderService, logger)
	feedbackHandler := feedback.NewFeedbackHandler(feedbackService, userHandler, customerHandler, logger)
	tenderApprovalHandler := tender_approval.NewHandler(tenderApprovalService, logger)

	logger.Info("Handlers initialized successfully", map[string]interface{}{
		"handlers": []string{"customer", "user", "company", "tender", "feedback", "tender_approval"},
	})

	// Initialize HTTP server
	e := bootstrap.InitHTTPServer(conf, logger)

	// Register routes
	router.RegisterAdminRoutes(e, userHandler, companyHandler, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler)
	router.RegisterPublicRoutes(e, customerHandler, tenderHandler, feedbackHandler, tenderApprovalHandler, companyHandler)

	// Start server
	serverAddr := fmt.Sprintf("%s:%d", conf.Server.Host, conf.Server.Port)
	logger.Info("HTTP server starting", map[string]interface{}{
		"address": serverAddr,
		"version": "1.0.0",
		"host":    conf.Server.Host,
		"port":    conf.Server.Port,
	})

	if err := e.Start(serverAddr); err != nil && err != http.ErrServerClosed {
		logger.Error("Failed to start HTTP server", map[string]interface{}{
			"error":   err.Error(),
			"address": serverAddr,
			"version": "1.0.0",
			"host":    conf.Server.Host,
			"port":    conf.Server.Port,
		})
		panic(fmt.Sprintf("Failed to start HTTP server: %v", err))
	}
}
