/**
 * @file no-hardcoded-routes.js
 * Enforces use of RouteConfig.ts instead of hardcoded route strings
 * 
 * This rule prevents hardcoded route strings in:
 * - router.push() / router.replace()
 * - redirect()
 * - Link href
 * - a href
 * - revalidatePath()
 * - Any string literal matching route patterns
 */

module.exports = {
  meta: {
    type: 'problem',
    docs: {
      description: 'Enforce use of RouteConfig.ts instead of hardcoded route strings',
      category: 'Best Practices',
      recommended: true,
    },
    fixable: 'code',
    schema: [],
    messages: {
      hardcodedRoute: 'Hardcoded route "{{route}}". Use routes from RouteConfig.ts instead: import { routes } from "@/lib/routing/RouteConfig"',
      hardcodedRedirect: 'Hardcoded redirect route "{{route}}". Use routes from RouteConfig.ts',
      hardcodedLink: 'Hardcoded link href "{{route}}". Use routes from RouteConfig.ts',
      hardcodedAnchor: 'Hardcoded anchor href "{{route}}". Use routes from RouteConfig.ts',
      hardcodedRevalidate: 'Hardcoded revalidatePath "{{route}}". Use routes from RouteConfig.ts',
    },
  },

  create(context) {
    // Route patterns that should be in RouteConfig
    const routePatterns = [
      '^/auth/',
      '^/public/',
      '^/protected/',
      '^/sponsor/',
      '^/admin/',
      '^/league(s)?/',
      '^/race(s)?/',
      '^/team(s)?/',
      '^/driver(s)?/',
      '^/leaderboard(s)?/',
      '^/error/',
      '^/404$',
      '^/500$',
      '^/dashboard$',
      '^/onboarding$',
      '^/profile',
      '^/sponsor/signup$',
    ];

    // Allowed exceptions (non-route paths)
    const allowedPaths = [
      '^/api/',
      '^/legal/',
      '^/terms$',
      '^/privacy$',
      '^/support$',
      '^/$', // root is allowed
    ];

    function isHardcodedRoute(value) {
      if (typeof value !== 'string') return false;
      
      // Check if it's an allowed path
      if (allowedPaths.some(pattern => new RegExp(pattern).test(value))) {
        return false;
      }
      
      // Check if it matches a route pattern
      return routePatterns.some(pattern => new RegExp(pattern).test(value));
    }

    function getRouteConfigSuggestion(route) {
      // Map common routes to RouteConfig suggestions
      const routeMap = {
        '/auth/login': 'routes.auth.login',
        '/auth/signup': 'routes.auth.signup',
        '/auth/forgot-password': 'routes.auth.forgotPassword',
        '/auth/reset-password': 'routes.auth.resetPassword',
        '/': 'routes.public.home',
        '/leagues': 'routes.public.leagues',
        '/drivers': 'routes.public.drivers',
        '/teams': 'routes.public.teams',
        '/leaderboards': 'routes.public.leaderboards',
        '/races': 'routes.public.races',
        '/sponsor/signup': 'routes.public.sponsorSignup',
        '/dashboard': 'routes.protected.dashboard',
        '/onboarding': 'routes.protected.onboarding',
        '/profile': 'routes.protected.profile',
        '/profile/settings': 'routes.protected.profileSettings',
        '/profile/leagues': 'routes.protected.profileLeagues',
        '/profile/liveries': 'routes.protected.profileLiveries',
        '/profile/liveries/upload': 'routes.protected.profileLiveryUpload',
        '/profile/sponsorship-requests': 'routes.protected.profileSponsorshipRequests',
        '/sponsor': 'routes.sponsor.root',
        '/sponsor/dashboard': 'routes.sponsor.dashboard',
        '/sponsor/billing': 'routes.sponsor.billing',
        '/sponsor/campaigns': 'routes.sponsor.campaigns',
        '/sponsor/leagues': 'routes.sponsor.leagues',
        '/sponsor/settings': 'routes.sponsor.settings',
        '/admin': 'routes.admin.root',
        '/admin/users': 'routes.admin.users',
        '/404': 'routes.error.notFound',
        '/500': 'routes.error.serverError',
      };

      // Check for parameterized routes
      const leagueMatch = route.match(/^\/leagues\/([^\/]+)$/);
      if (leagueMatch) {
        return `routes.league.detail('${leagueMatch[1]}')`;
      }

      const raceMatch = route.match(/^\/races\/([^\/]+)$/);
      if (raceMatch) {
        return `routes.race.detail('${raceMatch[1]}')`;
      }

      const teamMatch = route.match(/^\/teams\/([^\/]+)$/);
      if (teamMatch) {
        return `routes.team.detail('${teamMatch[1]}')`;
      }

      const driverMatch = route.match(/^\/drivers\/([^\/]+)$/);
      if (driverMatch) {
        return `routes.driver.detail('${driverMatch[1]}')`;
      }

      const sponsorLeagueMatch = route.match(/^\/sponsor\/leagues\/([^\/]+)$/);
      if (sponsorLeagueMatch) {
        return `routes.sponsor.leagueDetail('${sponsorLeagueMatch[1]}')`;
      }

      const leagueAdminMatch = route.match(/^\/leagues\/([^\/]+)\/schedule\/admin$/);
      if (leagueAdminMatch) {
        return `routes.league.scheduleAdmin('${leagueAdminMatch[1]}')`;
      }

      return routeMap[route] || null;
    }

    function reportHardcodedRoute(node, value, messageId, data = {}) {
      const suggestion = getRouteConfigSuggestion(value);
      const messageData = {
        route: value,
        ...data,
      };

      context.report({
        node,
        messageId,
        data: messageData,
        fix(fixer) {
          if (suggestion) {
            return fixer.replaceText(node, suggestion);
          }
          return null;
        },
      });
    }

    return {
      // Check router.push() and router.replace()
      CallExpression(node) {
        if (node.callee.type === 'MemberExpression' &&
            (node.callee.property.name === 'push' || node.callee.property.name === 'replace')) {
          
          // Check if it's router.push/replace
          const calleeObj = node.callee.object;
          if (calleeObj.type === 'Identifier' && calleeObj.name === 'router') {
            const arg = node.arguments[0];
            if (arg && arg.type === 'Literal' && isHardcodedRoute(arg.value)) {
              reportHardcodedRoute(arg, arg.value, 'hardcodedRoute');
            }
          }
        }

        // Check redirect()
        if (node.callee.type === 'Identifier' && node.callee.name === 'redirect') {
          const arg = node.arguments[0];
          if (arg && arg.type === 'Literal' && isHardcodedRoute(arg.value)) {
            reportHardcodedRoute(arg, arg.value, 'hardcodedRedirect');
          }
        }

        // Check revalidatePath()
        if (node.callee.type === 'Identifier' && node.callee.name === 'revalidatePath') {
          const arg = node.arguments[0];
          if (arg && arg.type === 'Literal' && isHardcodedRoute(arg.value)) {
            reportHardcodedRoute(arg, arg.value, 'hardcodedRevalidate');
          }
        }
      },

      // Check Link href
      JSXOpeningElement(node) {
        if (node.name.type === 'JSXIdentifier' && node.name.name === 'Link') {
          const hrefAttr = node.attributes.find(attr => 
            attr.type === 'JSXAttribute' && attr.name.name === 'href'
          );
          
          if (hrefAttr && hrefAttr.value && hrefAttr.value.type === 'Literal') {
            const value = hrefAttr.value.value;
            if (isHardcodedRoute(value)) {
              reportHardcodedRoute(hrefAttr.value, value, 'hardcodedLink');
            }
          }
        }

        // Check a href
        if (node.name.type === 'JSXIdentifier' && node.name.name === 'a') {
          const hrefAttr = node.attributes.find(attr => 
            attr.type === 'JSXAttribute' && attr.name.name === 'href'
          );
          
          if (hrefAttr && hrefAttr.value && hrefAttr.value.type === 'Literal') {
            const value = hrefAttr.value.value;
            if (isHardcodedRoute(value)) {
              reportHardcodedRoute(hrefAttr.value, value, 'hardcodedAnchor');
            }
          }
        }
      },

      // Check template literals in href
      JSXAttribute(node) {
        if (node.name.name === 'href' && node.value && node.value.type === 'JSXExpressionContainer') {
          const expr = node.value.expression;
          if (expr.type === 'TemplateLiteral') {
            // Check if template literal contains hardcoded route
            for (const quasi of expr.quasis) {
              if (quasi.value && isHardcodedRoute(quasi.value.raw)) {
                reportHardcodedRoute(quasi, quasi.value.raw, 'hardcodedLink');
              }
            }
          }
        }
      },

      // Check string literals in general (catches other cases)
      Literal(node) {
        if (typeof node.value === 'string' && isHardcodedRoute(node.value)) {
          // Skip if it's already being handled by more specific checks
          const parent = node.parent;
          
          // Skip if it's in a comment or already reported
          if (parent.type === 'Property' && parent.key === node) {
            return; // Object property key
          }
          
          // Check if this is in a context we care about
          let isInRelevantContext = false;
          let messageId = 'hardcodedRoute';
          
          // Walk up to find context
          let current = parent;
          while (current) {
            if (current.type === 'CallExpression') {
              if (current.callee.type === 'MemberExpression') {
                const prop = current.callee.property.name;
                if (prop === 'push' || prop === 'replace') {
                  isInRelevantContext = true;
                  break;
                }
              }
              if (current.callee.type === 'Identifier') {
                const name = current.callee.name;
                if (name === 'redirect' || name === 'revalidatePath') {
                  isInRelevantContext = true;
                  messageId = name === 'redirect' ? 'hardcodedRedirect' : 'hardcodedRevalidate';
                  break;
                }
              }
            }
            current = current.parent;
          }
          
          if (isInRelevantContext) {
            reportHardcodedRoute(node, node.value, messageId);
          }
        }
      },
    };
  },
};
