/*
 * Project: Video Sharing Platform
 * Year: 2026
 * Developed by: Molla Samser (Founder of RSK World)
 * 
 * Authentication and user management system.
 */

package main

import (
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
)

type User struct {
	ID          int       `json:"id"`
	Username    string    `json:"username"`
	Email       string    `json:"email"`
	DisplayName string    `json:"display_name"`
	Avatar      string    `json:"avatar"`
	Subscribers int       `json:"subscribers"`
	IsVerified  bool      `json:"is_verified"`
	CreatedAt   time.Time `json:"created_at"`
}

type LoginRequest struct {
	Email    string `json:"email"`
	Password string `json:"password"`
}

type RegisterRequest struct {
	Username    string `json:"username"`
	Email       string `json:"email"`
	Password    string `json:"password"`
	DisplayName string `json:"display_name"`
}

var users = []User{
	{ID: 1, Username: "mollasamser", Email: "molla@rskworld.in", DisplayName: "Molla Samser", Avatar: "https://rskworld.in/avatar1.jpg", Subscribers: 842109, IsVerified: true, CreatedAt: time.Now().AddDate(-1, 0, 0)},
	{ID: 2, Username: "rimakhatun", Email: "rima@rskworld.in", DisplayName: "Rima Khatun", Avatar: "https://rskworld.in/avatar2.jpg", Subscribers: 125000, IsVerified: true, CreatedAt: time.Now().AddDate(-0, -6, 0)},
}

var jwtSecret = []byte("rskworld_video_sharing_2026_secret_key")

func generateJWT(userID int, username string) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"user_id":  userID,
		"username": username,
		"exp":      time.Now().Add(time.Hour * 24 * 7).Unix(), // 7 days
	})

	return token.SignedString(jwtSecret)
}

func Login(c *gin.Context) {
	var req LoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Simulate authentication (in production, verify against database)
	for _, user := range users {
		if user.Email == req.Email {
			token, err := generateJWT(user.ID, user.Username)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"})
				return
			}

			c.JSON(http.StatusOK, gin.H{
				"status": "success",
				"token":  token,
				"user":   user,
			})
			return
		}
	}

	c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid credentials"})
}

func Register(c *gin.Context) {
	var req RegisterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Check if user already exists
	for _, user := range users {
		if user.Email == req.Email || user.Username == req.Username {
			c.JSON(http.StatusConflict, gin.H{"error": "User already exists"})
			return
		}
	}

	// Create new user
	newUser := User{
		ID:          len(users) + 1,
		Username:    req.Username,
		Email:       req.Email,
		DisplayName: req.DisplayName,
		Avatar:      fmt.Sprintf("https://api.dicebear.com/7.x/avataaars/svg?seed=%s", req.Username),
		Subscribers: 0,
		IsVerified:  false,
		CreatedAt:   time.Now(),
	}

	users = append(users, newUser)

	token, err := generateJWT(newUser.ID, newUser.Username)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"})
		return
	}

	c.JSON(http.StatusCreated, gin.H{
		"status": "success",
		"token":  token,
		"user":   newUser,
	})
}

func GetCurrentUser(c *gin.Context) {
	// Get user from token (simplified)
	userID := c.GetInt("user_id")
	if userID == 0 {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "Not authenticated"})
		return
	}

	for _, user := range users {
		if user.ID == userID {
			c.JSON(http.StatusOK, gin.H{"user": user})
			return
		}
	}

	c.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
}

func GetProfile(c *gin.Context) {
	username := c.Param("username")
	
	for _, user := range users {
		if user.Username == username {
			c.JSON(http.StatusOK, gin.H{
				"user": user,
				"videos_count": 12, // Mock data
				"total_views": "15.2M",
				"join_date": user.CreatedAt.Format("January 2006"),
			})
			return
		}
	}

	c.JSON(http.StatusNotFound, gin.H{"error": "Profile not found"})
}

func Subscribe(c *gin.Context) {
	creatorUsername := c.Param("username")
	// In production, this would update database
	
	c.JSON(http.StatusOK, gin.H{
		"status": "subscribed",
		"message": fmt.Sprintf("Subscribed to %s", creatorUsername),
	})
}

func generateSessionID() string {
	bytes := make([]byte, 16)
	rand.Read(bytes)
	return hex.EncodeToString(bytes)
}
